STL 集合的插入方法是否复制传递对象的值?
Does insert method of STL's set copy the value of passed objects?
我有这么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/)
因此,作为上面介绍的代码的结果,我应该得到一个仅包含清除IntSet
的SuperSet
。但是"不幸的是"这段代码有效 - 所有IntSet
都填充了正确的值......所以我的问题是 - STL 集合中的插入方法在其主体中真正做什么?它是否只是复制通过引用传递给它的对象?传递对象类型或基元类型之间的此方法行为有何区别?
感谢您的回答!
insert()
采用引用参数以避免在传递参数时复制。 但它会在将项目存储在集合中时创建副本。 这就是为什么clear()
在这种情况下可以工作的原因。 此外,在这两种情况下都是如此,因此即使您"重用"temp
,也会有单独的副本superSet
您的 SuperSet
声明按值存储IntSet
,因此插入新元素的唯一方法是制作副本。由于对原始IntSet
进行了更改,因此不会反映在副本中。
这特别适用于您将temp
传递给superSet
的方式,但在 C++11 中,您的使用效率变得低下。通过声明要用作临时的局部变量,可以通过强制创建副本来防止使用 move 语义。
SuperSet superSet;
for (DataType i = 0; i < noItems; i++)
{
superSet.insert(IntSet(&i, &i + 1));
}
打折优化 编译器将创建一个临时IntSet
并使用单个元素对其进行初始化。因为编译器知道这是一个临时的,所以它可以使用移动构造函数插入值。这将对传递的IntSet
执行浅拷贝,并将其值重置为默认状态(即指向 nullptr 的指针),从而导致移动。
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 在这种情况下,java对象是否可以调用本机函数
- 堆分配的对象是否存在永不为空的唯一所有者?
- QFileSystemModel 对象是否会被删除?
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 临时C++对象是否为左值?
- 为什么复制构造函数不需要检查输入对象是否指向自身?
- "this"指向的对象是否与 const 对象相同?
- 有什么方法可以检测我的类的对象是否在堆栈上创建
- 基类对象是否隐式添加到派生类中?
- 当 T 具有非平凡析构函数时,类类型 T 的对象是否可以常量初始化?
- 如何检查指针后面的对象是否有效或已删除?
- 谷神星求解器:残差函子使用的可变对象是否良好实践?还有什么其他选择
- 单一实例对象是否通过线程安全返回shared_ptr
- 对象是否保证在调用其成员函数之前被初始化
- 在另一个对象 B 中创建对象 A 时,对象 A 是否是对象 B 的本地对象,对象 A 是否会存在于对象 B 的实例化之外?
- 如何确定对象是否已分配成员
- 我们如何在c 中序列化或应对类的对象.是否有任何预定义的库
- 友元类对象是否可以在其成员函数中访问派生类对象的基类私有成员?