我对C++如何管理向量中的对象感到困惑.说我做以下事情:
vector<MyClass> myVector;
myVector.push_back(a);
myVector.push_back(b);
MyClass & c = myVector[1];
myVector.erase(myVector.begin());
Run Code Online (Sandbox Code Playgroud)
参考c是否仍然有效(或者更好,是否保证有效)?如果没有,我是否必须始终从参考文件中复制以确保安全?
pae*_*bal 12
与Java或C#引用(更像是C++引用而不是C++引用)不同,C++中的引用与指针一样"哑",这意味着如果获得对象的引用,然后将该对象移动到内存中,则引用不再有效.
参考c是否仍然有效(或者更好,是否保证有效)?
在您描述的情况下,当向量内容发生更改(删除项目,调整向量大小等)时,不保证标准向量不会将其包含的对象保留在内存中的相同位置.
这将使迭代器和对所包含对象的指针/引用无效.
如果没有,我是否必须始终从参考文件中复制以确保安全?
有多种方法可以继续"指向"正确的对象,所有这些方式都意味着一个间接层.
最简单的是制作MyClass的完整副本:
vector<MyClass> x ;
x.push_back(a) ;
x.push_back(b) ;
MyClass c = x[1] ; // c is a full copy of b, not a reference to b
x.erase(x.begin()) ;
Run Code Online (Sandbox Code Playgroud)
第二个最简单的方法是使用std::list专门为元素插入和删除而设计的a ,它不会更改包含的对象,也不会使指针,引用或迭代器无效:
list<MyClass> x ;
x.push_back(a) ;
x.push_back(b) ;
list<MyClass> it = x.begin() ;
++it ;
MyClass & c = *it ;
x.erase(x.begin()) ;
Run Code Online (Sandbox Code Playgroud)
另一种方法是制作一个std::vector<MyClass *>包含指针MyClass而不是MyClass对象的指针.然后,您将能够保持指向对象或对指向对象的引用,具有略微不同的表示法(因为额外的间接):
vector<MyClass *> x;
x.push_back(a); // a being a MyClass *
x.push_back(b); // b being a MyClass *
MyClass * c = x[1]; // c points to the same object as b
x.erase(x.begin()); // note that a will still need separate deallocation
Run Code Online (Sandbox Code Playgroud)
这是不安全的,因为没有明确的(就编译器而言)对象a和b的所有者,这意味着没有明确的代码负责在不再需要它们时解除分配它们(这就是内存泄漏的发生方式)在C和C++中)
因此,如果您使用此方法,请确保代码封装良好,并尽可能小以避免维护意外.
更好的是使用智能指针.例如,使用C++ 11(或boost)shared_ptr:
vector< shared_ptr<MyClass> > x;
x.push_back(a); // a being a shared_ptr<MyClass>
x.push_back(b); // b being a shared_ptr<MyClass>
shared_ptr<MyClass> c = x[1]; // c points to the same object as b
x.erase(x.begin()); // No deallocation problem
Run Code Online (Sandbox Code Playgroud)
现在,如果您使用shared_ptr并且一无所知weak_ptr,那么您就有问题,所以您应该缩小这个差距.
另一个解决方案是使用C++ 11 unique_ptr,它是尖头对象的独占所有者.因此,如果您想要指针或对指针对象的引用,则必须使用原始指针:
vector< unique_ptr<MyClass> > x;
x.push_back(a); // a being a unique_ptr<MyClass>
x.push_back(b); // b being a unique_ptr<MyClass>
MyClass * c = x[1].get(); // c points to the same object as b
x.erase(x.begin()); // No deallocation problem
Run Code Online (Sandbox Code Playgroud)
请注意,向量是对象的唯一所有者,与上面的情况不同smart_ptr.
您使用C++编写代码,这意味着您必须为您的问题选择正确的方法.
但首先,您需要确保了解指针添加的间接级别,指针的作用以及C++引用的作用(以及它们不是C#/ Java引用的原因).
参考 c 仍然有效(或者更好的是,它保证有效)吗?
不,它现在处于未定义状态。
如果没有,我是否必须始终复制参考资料以确保安全?
如果在您检索它和使用它之间它有可能被删除或移动(等),那么是的,您确实需要制作副本。
| 归档时间: |
|
| 查看次数: |
1880 次 |
| 最近记录: |