[英]How to return large vector from class without copying data
我正在編寫一個程序,其中一個類的數據成員是一個很大的std::vector
(大約100k-1M個項目)。 其他類需要能夠訪問此向量。 目前,我有一個返回向量的標准訪問器函數,但這將返回我相信的向量的副本。 我認為只返回一個迭代器或一個指向第一個元素的指針會節省更多的內存和時間。 但是,如果我這樣做,那么如何使用該指針遍歷vector
並知道何時停止(即向量結束於何處)?
我的代碼如下所示:
class MyClass
{
private:
std::vector<MyObj> objects_;
//...
public:
std::vector<MyObj> getObjects() { return objects_; }
//...
}
當我想遍歷(模擬)級聯向量時,這個問題對我來說又是另一種形式。 如果我有一個MyClass
的vector
,則希望能夠遍歷所有包含的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()...)
委托代碼如下:固定了調用代碼后,您可以改變主意,將哪種類型(向量,列表,集合)用作對象的內部容器,而無需更改調用代碼。
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);
使用這種方法,向量只有一個實例,但是可以通過兩種公開方法來進行任何協作,這兩種公開方法通過索引公開大小和訪問值的方法。
這種方法適合於使用for循環而不是迭代器。
MyClass myClass;
// ...
MyObj myObj;
for(unsigned int i; i < myClass.getMyObjArraySize(); i++) {
myObj = myClass.getMyObjElementAt(i);
// do stuff
}
返回指向向量的指針沒有問題。
std::vector<MyObj>* getObjects() { return &objects_; }
然后,當要對其進行迭代時,只需取消引用即可:
std::vector<MyObj>* objectsPtr = getObjects();
for (auto& it : *objectsPtr)
{
...
}
但是,請確保在讀取向量時未寫入向量,因為這會使迭代器無效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.