参考对象的STL容器

Ven*_*tta 28 c++ stl reference pass-by-reference

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

list<SampleClass> l;
Run Code Online (Sandbox Code Playgroud)

每当我这样做

SampleClass t(...);
l.push_back(t);
Run Code Online (Sandbox Code Playgroud)

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

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

list<SampleClass&> l;
Run Code Online (Sandbox Code Playgroud)

当我做

l.push_back(t);
Run Code Online (Sandbox Code Playgroud)

它会避免复制对象吗?

Ker*_* SB 32

如果您知道自己在做什么,可以使用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 };
}
Run Code Online (Sandbox Code Playgroud)

当然,请注意,如果任何引用的变量超出范围,而您仍然保留对它们的引用,那么任何这些都会崩溃.

  • 正确:我认为“reference_wrapper”应该优先于原始指针,以便清楚地传达非所有权,避免粗糙的指针语法(以换取破坏“auto”并且有时必须使用“.get()”。 ..),并避免未初始化的指针或“nullptr”或意外进行指针算术等的可能性。 (2认同)

Dav*_*ton 20

可悲的是,它不会编译(至少使用stlport).但另一种方法是在容器中存储指向对象的指针,它将完全编译.

这将为您的代码留下一些额外的语法噪音 - 您需要新的东西才能将它们插入到您的容器中.

std::list<class_type*> l;
l.push_back(new class_type);
Run Code Online (Sandbox Code Playgroud)

但是,虽然现在不会复制对象,但在销毁列表时也不会自动清除它们.智能指针将为您解决这个问题,但代价是更多的语法噪音.而且由于你无法将std :: auto_ptr放在标准容器中,因为它们无法被复制,你必须使用它们稍微加重的提升表兄弟,共享指针.

std::list<boost::shared_ptr<class_type> > l;
l.push_back(boost::shared_ptr<class_type>(new class_type));
Run Code Online (Sandbox Code Playgroud)

共享指针会产生一些额外的开销,但它是最小的.


Den*_*ose 5

标准库容器要求其类型可复制;由于引用不是,因此您一开始就无法将它们存储在容器中。只要注意对象的生命周期,您就可以存储指针。Boost 有一些指针容器来帮助解决这个问题,或者你有智能指针。但请注意,这auto_ptr不可复制的(因为标准为此目的定义了它),因此shared_ptrunique_ptr是您现在最好的选择。两者都是 C++11 中的标准,前者在 C++03 中通过 boost 支持。