给定 myvector.start() 和 myvector.end(),我想在不复制数据的情况下创建 myvector
Given myvector.start() and myvector.end() I want to create a read-only subset of myvector without copying the data. Is this possible, and how?
给定myvector.start()和myvector.end() 我想在不复制数据的情况下创建myvector的只读子集。
这可能吗,如何?
#include <iostream>
#include <vector>
using namespace std;
template <class T> void print_vector(const vector<T> &v) {
for(size_t i = 0; i < v.size(); ++i) std::cout << v[i] << " ";
std::cout << std::endl;
}
int main() {
首先,我创建向量。
vector<double> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print_vector(data); // 1 2 3 4 5 6 7 8 9 10
然后我想要一个子集。但我认为这是复制品。
// Does this make a copy or not? I don't want to make a copy.
const vector<double> subset1(data.begin() + 3, data.end() - 3);
print_vector(subset1); // 4 5 6 7
这种方法怎么样?
// Another approach. Questions:
// - Would something like this be a good alternative if I really don't want a copy?
// - How would the performance of this be compared to a normal STL container?
// - Is there an existing implementation of a container that does something like this, maybe a boost class?
class SubsetType {
public:
SubsetType(const vector<double>::iterator &start, const vector<double>::iterator &end) { begin_ = start; end_ = end; }
vector<double>::iterator begin() { return begin_; }
vector<double>::iterator end() { return end_; }
double operator[](vector<double>::size_type i) { return *(begin_ + i); }
vector<double>::size_type size() { return end_ - begin_; }
private:
vector<double>::iterator begin_, end_;
};
SubsetType subset2(data.begin() + 3, data.end() - 3);
for(size_t i = 0; i < subset2.size(); ++i) std::cout << subset2[i] << " ";
std::cout << std::endl; // 4 5 6 7
或者是声明所有函数的解决方案,例如 f(const vector::iterator &start, const vector::iterator &en)。STL算法就是这样做的,对吧?(但通用)
退出
std::cout << "Bye!" << std::endl;
return 0;
}
只需使用迭代器(在适当的情况下使用常量)。
如果你真的对到处传递开始/结束对过敏,请考虑使用 Boost.Range 或类似的东西:它可以让您将[start,end)
对捆绑到单个对象中。
如果您不想要副本,请遵循与 std:: 算法库相同的习语,并使用开始和结束迭代器。 迭代器重量轻,不承担复制操作的成本。
在 C++11 中,所有容器都获得了 cbegin()
和 cend()
函数,这允许您从非 const 容器创建const_iterator
。之后,只需修改您的算法以接受开始和结束迭代器,您就完成了。
print_range(data.cbegin()+3, data.cend()-3);
如果您坚持使用 C++03,您可以使用轻转发功能将任何对象转换为其const
版本:
template<class T>
T const& as_const(T const& v){ return v; }
然后:
print_range(as_const(data).begin()+3, as_const(data).end()-3);
或者是声明所有函数的解决方案,例如 f(const vector::iterator &start, const vector::iterator &en)。
是的。
STL算法就是这样做的,对吧?(但通用)
是的。一般也这样做。标准库算法是一个很好的建模示例。
增强范围将接近您的预期。
下面的示例显示了一个示例
- 使用切片适配器创建矢量的子范围"视图"(无副本)
- 显示修改原始(底层)矢量元素会导致该视图中的数据发生更改
- 使用
make_iterator_range
来执行大致相同的操作。
请注意,适配器是比简单迭代器范围更灵活的抽象。
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
using namespace boost::adaptors;
int main(int argc, const char *argv[])
{
std::vector<int> v { 0, 1, 2, 3, 4, 5, 6 };
auto output = std::ostream_iterator<int>(std::cout, ",");
auto&& slice = v | sliced(2, 5);
boost::copy(slice, output);
std::cout << 'n';
v[3] += 10;
boost::copy(slice, output);
std::cout << 'n';
/// Alternative without adaptors:
auto range = boost::make_iterator_range(v.begin()+3, v.end());
boost::copy(range, output);
std::cout << 'n';
}
在 http://liveworkspace.org/code/5be869c15f534b6161e61c392c181f2d 上观看直播
执行输出:
2,3,4,
2,13,4,
13,4,5,6,
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- 以下示例中如何避免代码复制?C++/库达
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 文件系统:复制功能的速度秘诀是什么
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在 MyVector 中实现写入时复制习语
- 给定 myvector.start() 和 myvector.end(),我想在不复制数据的情况下创建 myvector