我知道STL容器会复制对象。所以说我有一个
list<SampleClass> l;
每次我做的时候
SampleClass t(...);
l.push_back(t);
将制作一份副本。如果SampleClass很大,那么它将非常昂贵。
但是如果我将l声明为引用的容器,
list<SampleClass&> l;
当我这样做时
l.push_back(t);
是否会避免复制对象?
答案 0 :(得分:31)
如果您知道自己在做什么,可以使用std::reference_wrapper
制作参考文献:
#include <functional>
#include <vector>
int main()
{
std::vector<std::reference_wrapper<int>> iv;
int a = 12;
iv.push_back(a); // or std::ref(a)
// now iv = { 12 };
a = 13;
// now iv = { 13 };
}
当然注意,如果任何引用的变量超出范围而你仍然持有对它们的引用,那么任何这些都会崩溃。
答案 1 :(得分:19)
可悲的是,它不会编译(至少使用stlport)。但另一种方法是在容器中存储指向对象的指针,编译完全正确。
这将为您的代码留下一些额外的语法噪音 - 您需要新的东西才能将它们插入容器中。
std::list<class_type*> l;
l.push_back(new class_type);
但是,虽然现在不会复制对象,但在销毁列表时也不会自动清除它们。智能指针将为您解决这个问题,但代价是更多的语法噪音。而且由于你无法将std :: auto_ptr放在标准容器中,因为它们无法被复制,你必须使用它们稍微重量级的提升表兄弟,共享指针。
std::list<boost::shared_ptr<class_type> > l;
l.push_back(boost::shared_ptr<class_type>(new class_type));
共享指针会产生一些额外的开销,但它很小。
答案 2 :(得分:4)
标准库容器要求其类型可以复制;由于引用不是,您不能将它们存储在容器中。你可以存储指针,只要你注意对象的生命周期。 Boost有一些指针容器来帮助它,否则你有智能指针。但请注意,auto_ptr
不可复制(因为标准为此目的定义了它),因此shared_ptr
和unique_ptr
是您最好的赌注。两者都是C ++ 11中的标准,前者通过C ++ 03中的boost得到支持。
答案 3 :(得分:0)
你想要一个指针容器:
list<SampleClass*> l;
答案 4 :(得分:0)
现在您已经拥有了智能指针,您可以使用它进行内存管理并从中获取原始指针以在STL容器中使用。通过这种方式,您可以将所有权保留在容器之外。
这里我有一个树的unique_ptr,但是使用STL堆栈来存储原始指针
void TreeTraversal(unique_ptr<BinaryTreeNode>& root) {
stack<BinaryTreeNode *> _stack;
BinaryTreeNode *p = root.get();
_stack.push(p);
while(!_stack.empty()) {
p = _stack.top();
_stack.pop();
...
_stack.push(p->left);
_stack.push(p->right);
}
}
int main() {
unique_ptr<BinaryTreeNode> root = unique_ptr<BinaryTreeNode>(new BinaryTreeNode(...));
TreeTraversal(root);
}