如何从类返回大向量而不复制数据
How to return large vector from class without copying data
我正在编写一个程序,其中一个类具有一个大std::vector
的数据成员(在100k - 1M项的顺序上)。其他类需要能够访问这个向量。目前,我有一个返回vector的标准访问函数,但我认为这里返回的是vector的副本。我认为直接返回一个迭代器或指向第一个元素的指针会更节省内存和时间。然而,如果我这样做,那么如何使用这个指针通过vector
运行,并知道何时停止(即向量结束的地方)?
我的代码是这样的:
class MyClass
{
private:
std::vector<MyObj> objects_;
//...
public:
std::vector<MyObj> getObjects() { return objects_; }
//...
}
当我想运行(模拟)连接向量时,这个问题以另一种形式出现。如果我有vector
(MyClass
),我希望能够遍历所有包含的object_
向量。我从这个答案中知道boost::join做了我想要的,但我想我需要返回副本才能工作。我可以返回一个指向向量的指针,并且仍然保留对它和其他连续迭代的能力吗?
为了避免性能损失,返回引用。
// Non-const version
std::vector<MyObj>& getObjects() { return objects_;}
// const version
std::vector<MyObj> const& getObjects() const { return objects_; }
但是,在进行更改之前,必须考虑公开对成员变量的引用的缺点。它使你的课程不那么灵活。如果将objects_
更改为另一种类型的容器更有意义,而不影响该类的所有用户,则无法轻松地将其更改为其他类型的容器。
通过委托给vector
数据成员,使您的类充当集合。当然,您可能需要重新访问使用MyClass
的代码但是,注释掉getObjects()
之后,编译器会告诉你大部分的修改可能在
MyClass heapsOfThem;
// ...
// just delete the `getObjects()` *and use MyClass::iterator*
// instead of std::vector::iterator.
// for(std::vector<MyObj>::iterator it=
// heapsOfThem.getObjects().begin()...
// )
for(MyClass::iterator it=heapsOfThem.begin()...)
委托代码在下面一行——一旦你修复了你的调用代码,你可以改变你的想法,使用什么类型(vector, list, set)作为你的对象的内部容器,而不改变调用代码。
class MyClass
{
private:
std::vector<MyObj> objects_;
//...
public:
const size_t size() const {
return objects_,size();
}
MyObj& operator[](size_t i) {
return objects_[i];
}
const MyObj& operator[](size_t i) const {
return objects_[i];
}
using iterator = std::vector<MyObj>::iterator;
iterator begin() {
return objects_.begin();
}
iterator end() {
return objects_.end();
}
// TODO const iterators following the same pattern
// *if you aren't good enough with the above*
// uncomment it and let it return a *reference*
// std::vector<MyObj>& getObjects() { return objects_; }
//...
}
您可以重构类,使其具有返回数组元素和数组大小的公共方法,因此所有其他类都可以获取值,而无需复制整个向量。
public:
unsigned int getMyObjArraySize();
MyObj getMyObjElementAt(unsigned int index);
使用这种方法,只有一个vector实例,但任何协作都可以通过两个公开size的公共方法和通过索引访问值的访问器来完成。
这种方法适合使用for循环而不是迭代器。
MyClass myClass;
// ...
MyObj myObj;
for(unsigned int i; i < myClass.getMyObjArraySize(); i++) {
myObj = myClass.getMyObjElementAt(i);
// do stuff
}
返回指向vector的指针是没有问题的。
std::vector<MyObj>* getObjects() { return &objects_; }
然后当你想对它进行迭代时,只需解引用:
std::vector<MyObj>* objectsPtr = getObjects();
for (auto& it : *objectsPtr)
{
...
}
但是,请确保在从vector对象中读取数据的同时没有写入vector对象,因为这样会使迭代器失效。
- 在 C++ AMP 数组中复制数据多少次?
- 字符串是否在其构造函数中复制数据
- 在不复制数据的情况下,将double数组转换为只有double成员的structs数组
- 有没有一种方法可以在不复制数据的情况下从string_view创建字符串流
- 如何在不复制数据的情况下将 cv::Mat 转换为 2d 标准::矢量
- C++ 在节点内存储对数据对象的引用,而不复制数据
- 是否可以在不分配内存或复制数据的情况下构造对象?
- 如何在不复制数据的情况下在平面数组和多维数组之间进行转换?
- C 2D char阵列有时会在随机位置复制数据
- 在不复制数据的情况下更改 opencv mat 中的列顺序
- 有没有办法将 EGL 绘制到 /dev/fb1 而不是 /dev/fb0,而无需在树莓派上复制数据
- 使用C 和目标C从原始图像中复制数据
- 给定 myvector.start() 和 myvector.end(),我想在不复制数据的情况下创建 myvector
- 复制数据时出现奇怪错误
- 如何在 C/C++ 中从数组末尾开始复制数据
- glTexImage2D 复制数据或仅指定数据
- 如何在C++中从void指针复制数据
- 在不复制数据的情况下将OpenCV Mat发送到MATLAB工作区的方法
- 如何使用 GPU-DMA 从 GPU-CUDA 代码来复制数据
- 在矢量到矢量中复制数据<float> <Mat> (Opencv/C++)