STL的set方法是否复制了传递对象的值?

时间:2012-06-07 22:37:11

标签: c++ stl insert set

我有这样的C ++代码(请不要问为什么它看起来如此丑陋;) - 你必须相信,因为代码的更多部分它真的有意义):

IntSet temp;
SuperSet superSet;
for (uint i = 0; i < noItems; i++) {
        temp.insert(i);
        superSet.insert(temp);
        temp.clear();
}

它用于准备noItems个整数集(IntSet,每个整数包含一个整数值)并将其插入其他集合(SuperSet)。两组定义如下:

typedef unsigned int DataType;
typedef std::set<DataType> IntSet;
typedef std::set<IntSet> SuperSet;

对我来说,此代码不应按预期工作,因为在将temp插入superSet之后我正在清除temp,我发现insert获取参考作为其参数:pair<iterator,bool> insert ( const value_type& x );http://www.cplusplus.com/reference/stl/set/insert/

因此,作为上述代码的结果,我应该得到仅包含已清除SuperSet的{​​{1}}。但“不幸的是”这段代码有效 - 所有IntSet都填充了正确的值......所以我的问题是 - 来自STL集合的插入方法在其体内是做什么的?它是否只是复制通过引用传递给它的对象?这个方法在传递对象或基元类型之间的行为有什么不同?

感谢您的回答!

2 个答案:

答案 0 :(得分:1)

insert()接受引用参数以在传递参数时避免复制。但是在将项目存储在集合中时会创建副本。这就是clear()在这种情况下可以工作的原因。此外,在这两种情况下都是如此,因此即使您“重复使用”tempsuperSet

中也会有单独的副本

答案 1 :(得分:0)

您按{值{1}}存储SuperSet的声明,因此插入新元素的唯一方法是制作副本。由于副本已对原始IntSet进行更改,因此不会反映在副本中。

这特别适用于您将IntSet传递给temp的方式,但在C ++ 11中,您的使用效率低下。通过声明一个局部变量用作临时变量,可以通过强制复制来阻止使用移动语义。

superSet

折扣优化编译器将创建一个临时SuperSet superSet; for (DataType i = 0; i < noItems; i++) { superSet.insert(IntSet(&i, &i + 1)); } 并使用单个元素对其进行初始化。因为编译器知道这是临时的,所以它可以使用移动构造函数插入值。这将执行IntSet传递的浅表副本,并将其值重置为默认状态(即指向nullptr的指针),从而导致移动