与智能指针相关的c++移动语义与复制构造函数和赋值操作符
C++ Move Semantics vs Copy Constructor and Assignment Operator in relation to Smart Pointers
我想弄清楚什么时候使用移动语义,什么时候使用复制构造函数和赋值运算符作为经验法则。你在类中使用的指针类型(如果有的话)似乎受到这个答案的影响,所以我包含了这个。
没有指针 -根据这个答案,如果您有一个具有int和string等基本类型的POD类,则不需要编写自定义移动或复制构造函数和操作符。
unique-ptr -基于这个答案,当使用move语义时,unique_ptr比shared_ptr更适合,因为资源只能有一个unique_ptr。
shared_ptr -同样,如果使用复制语义,shared_ptr似乎是可行的。对象可以有多个副本,所以拥有一个指向资源的共享指针对我来说是有意义的。然而,unique_ptr通常比shared_ptr更可取,所以如果可以的话,请避免使用该选项。
但:
- 我什么时候应该使用移动语义?
- 我什么时候应该使用复制语义?
- 我应该两者都用吗?
- 我应该使用none并依赖默认的复制构造函数和赋值操作符吗?
顾名思义,当资源必须只有一个所有者时,使用unique_ptr
。unique_ptr
的复制构造函数被禁用,这意味着不可能存在它的两个实例。然而,它是可移动的……这很好,因为这允许所有权转移。
顾名思义,shared_ptr
表示资源的共享所有权。然而,这两个智能指针之间还有另一个区别:unique_ptr
的Deleter
是其类型签名的一部分,但它不是shared_ptr
的类型签名的一部分。这是因为shared_ptr
使用"类型擦除"来擦除删除器的"类型"。还要注意,shared_ptr
也可以移动来转移所有权(像unique_ptr
一样)
我什么时候应该使用移动语义?
虽然shared_ptr
可以被复制,但当你进行所有权转移时(而不是创建一个新的引用),你可能想要移动它们。你有义务对unique_ptr
使用move语义,因为所有权必须是唯一的。
何时应该使用复制语义?
在智能指针的情况下,您应该使用复制来增加shared_ptr
s的引用计数(如果您不熟悉引用计数的概念,请研究引用计数垃圾收集)
我应该两者都用吗?
是的。如上所述,shared_ptr
既可以复制也可以移动。复制表示增加引用计数,而移动仅表示所有权的转移(引用计数保持不变)
应该使用none并依赖默认的复制构造函数和赋值操作符吗?
当你想对一个对象进行逐个成员的复制时。
-
我什么时候应该使用移动语义?
我想你的意思是,"我应该什么时候给我的类一个move构造函数?"答案是每当移动这种类型的对象是有用的,而默认的移动构造函数不能正确地完成这项工作时。当将资源从一个对象转移到另一个对象时,移动是有用的。例如,移动对
std::string
很有用,因为它允许从临时对象复制对象,而无需重新分配和复制其内部资源,而只需将资源从一个对象移动到另一个对象。许多类型将从中受益。另一方面,移动对std::unique_ptr
很有用,因为这是唯一一种通过值传递std::unique_ptr
而不违反其"唯一所有权"的方法。 -
我什么时候应该使用复制语义?
再一次,我假定你的意思是,"我什么时候应该给我的类一个复制构造函数?"当您需要能够复制对象时,其中内部资源在它们之间进行复制,并且默认复制构造函数不能正确地完成这项工作。复制对于几乎任何类型都是有用的,除了像
std::unique_ptr
这样必须对内部资源强制唯一所有权的类型。 -
我应该两者都用吗?
在大多数情况下,你的类应该同时提供复制和移动语义。最常见的类应该是可复制和可移动的。可复制提供了按值传递对象的标准语义。可移动允许按值传递临时对象时可以获得的优化。这是否意味着必须提供复制或移动构造函数取决于默认构造函数是否做适当的事情。 -
我应该使用none并依赖默认的复制构造函数和赋值操作符吗?
默认的copy和move构造函数只是分别复制或移动类的每个成员。如果这种行为适合复制和移动类,那就太好了。大多数情况下,这就足够了。例如,如果我有一个包含
std::string
的类,默认的复制构造函数将复制字符串,默认的移动构造函数将把字符串的资源移动到新对象中——两者都做适当的工作。如果您的类包含std::unique_ptr
,则复制将无法工作,并且您的类将只能移动。这可能是您想要的,或者您可能想要实现一个复制构造函数来执行资源的深度拷贝。应该实现复制/移动构造函数的最重要的情况是当类本身执行资源管理时(例如使用new
和delete
)。如果是这种情况,默认构造函数几乎永远不会很好地管理这些资源。
- 使用移动和复制语义时函数匹配如何工作?
- 移动语义和深层/浅层复制之间有什么关系?
- 了解构造函数在移动、复制、赋值语义中的行为
- 是否可以/希望创建不可复制的共享指针模拟(以启用weak_ptr跟踪/借用类型语义)?
- 复制省略并在返回值中移动语义
- 在一个微不足道的可复制结构中,移动语义应该实现吗?
- 在'string=string+s1'和"string+=s1"之间移动语义可以保存多少个复制操作?
- C++复制构造函数和移动语义之间的区别
- 默认情况下,返回是否使用移动或复制语义
- 我应该依赖复制省略还是移动语义
- 在封装指针的类中,移动语义无意中被复制构造函数取代
- 为什么 boost::make_shared 使用复制语义
- 复制有状态分配器:标准库分配器语义和内部内存
- 每次复制实现移动分配的非 const 对象时,我是否总是获得移动语义
- 如何使用C 11移动语义以明确避免复制
- 有没有一种非重复的方法允许程序员在成员初始化的复制和移动语义之间进行选择
- 从具有移动语义或返回值优化的函数返回值,但不返回复制构造函数
- 复制C++唯一指针的语义
- 链表复制/移动语义C++
- C++移动语义:为什么调用复制赋值运算符=(&)而不是移动赋值运算符=(&&)?