STL:存储引用还是值?

13

我一直对STL容器(如vector、list、map等)如何存储值感到有些困惑。它们是存储对我传递的值的引用,还是复制/复制构造并自行存储这些值?

例如,

int i;
vector<int> vec;
vec.push_back(i);
// does &(vec[0]) == &i;

class abc;
abc inst;
vector<abc> vec;
vec.push_back(inst);
// does &(vec[0]) == &inst;
感谢。

5
你已经有了我看起来像是可行的代码,可以测试答案(只需稍作修改即可将注释变为条件语句)。运行它并查看结果吧!我相当确定它们会进行复制构造和存储。 - Dominic Rodger
2个回答

19

STL容器会复制构造并存储传入的值。如果你想在容器中存储对象但是不想复制它们,我建议在容器中存储指向对象的指针:

class abc;
abc inst;
vector<abc *> vec;
vec.push_back(&inst);

这是实现容器类以防止意外存储不可用栈帧上的变量引用的最合理方法。考虑以下情况:

class Widget {
public:
    void AddToVector(int i) {
        v.push_back(i);
    }
private:
    vector<int> v;
};

如果存储对 i 的引用,会很危险,因为在从定义该变量的方法返回后,您将引用局部变量的内存位置。


5
在C++中,您不能创建存储引用的容器。传递给容器的类型参数必须是可分配的。引用是不可分配的,它们被初始化为一个对象,但在构造后不能被指定为引用另一个对象。因此,引用类型不满足在容器内使用的类型要求。如果您想具有相同的语义(或尽可能接近),您必须提供一个引用包装器(boost::ref/boost::cref)。 - David Rodríguez - dribeas
3
@dribeas:这个答案通过解释虚构实现的风险来解释为什么不这样做。 - MSalters

4

这取决于你的类型。如果它是一个简单值类型,并且复制成本低廉,那么存储值可能是答案。另一方面,如果它是引用类型或复制成本高昂,则最好存储智能指针(不要使用auto_ptr,因为它的特殊复制语义会防止其被存储在容器中。选择shared_ptr)。使用裸指针会冒着内存泄漏和访问已释放内存的风险,而使用引用则冒着后者的风险。智能指针避免了这两个问题。


2
在容器中使用智能指针来处理内存的操作是一个不错的选择。另外一个选择可以是使用像Boost Pointer Container这样的库来管理资源释放。 - David Rodríguez - dribeas
5
这不是 OP 所询问的内容。他想知道当值放入容器时,容器类本身是否会复制该值。答案是,是的,它们会 -- 这就是为什么如果特定类型的复制成本很高,存储指针可能是一个好选择。 - Dan Moulding
2
如果你知道自己在做什么并且在使用后进行清理,存储裸指针是完全可以的。 - Brian Neal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接