参考对象的STL容器

时间:2011-10-10 01:52:46

标签: c++ stl reference pass-by-reference

我知道STL容器会复制对象。所以说我有一个

list<SampleClass> l;

每次我做的时候

SampleClass t(...);
l.push_back(t);

将制作一份副本。如果SampleClass很大,那么它将非常昂贵。

但是如果我将l声明为引用的容器,

list<SampleClass&> l;

当我这样做时

l.push_back(t);

是否会避免复制对象?

5 个答案:

答案 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_ptrunique_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);
}