显式移动构造函数?

31

explicit关键字建议用于可以接受一个参数的所有大多数构造函数,但不包括拷贝构造函数。

对于拷贝构造函数,它有一定的用途(禁止通过函数调用、返回等方式进行隐式复制),但这通常并不是所需的。

那么移动构造函数呢?有什么合理的使用情况使它们变得显式吗?在这里应该遵循什么样的最佳实践?


“复制构造函数”和“可以用一个参数调用的构造函数”有什么区别?我刚才对DeadMG的回答感到有些困惑,因为我认为它们是一样的。这只是它们的使用方式不同,而且(除了“显式”的情况)并不影响构造函数的声明,是吗?还是我已经疯了? - user180247
3
单参数复制构造函数是指构造函数 T([const] [volatile] T&)。参见12.8/2。T(int) 是一个可以用一个参数调用的构造函数,但不是复制构造函数,因为它不会“复制”一个 T 的实例。 - Steve Jessop
@Steve Jessop - 是的,当然。显然我脑子短路了。 - user180247
谢谢回答!那么我们可以认为,没有合理的(即明显有益的)理由使其明确吗? - Kos
在C++0x中,对于只能为多个参数调用的构造函数也建议使用它。 - Johannes Schaub - litb
@Johannes Schaub,你的意思是在C++0x中有些情况下explicit关键字会对这样的构造函数产生影响吗?你能举个例子吗? - Kos
5个回答

29
一个显式的移动构造函数可能会影响与标准算法等的兼容性。例如,std::swap<T>要求T是可移动构造的。而可移动构造是根据一个表达式来指定的,即T u = rv;(其中rv是类型为T的右值)。
如果给定类型既没有非显式的复制构造函数,也没有非显式的移动构造函数,那么T u = rv;就无效了,这种类型不能与std::swap一起使用。(但在这个特定实例中,可以通过专门化std::swap来提供所需的功能,例如使用T u(rv);)。
更简单地说,显式的移动或复制构造函数违反了预期,不能与通用代码一起使用。
标准库的一些其他部分也要求可移动构造:
  • unique_ptr<T, D>的删除器
  • bind中使用的调用包装器(涉及传递的所有衰减类型)
  • threadasynccall_once(都是以调用包装器作为指定方式)
  • sortstable_sortnth_elementsort_heap

7

大多数情况下,您可能希望使用隐式移动构造函数。它们通常与拷贝构造函数属于相同的类别。不是所有的单参数构造函数都建议使用显式构造函数,但大多数情况下建议使用。移动构造函数不在该列表中。


7
< p > 建议在(单参数)转换构造函数中使用 explicit 关键字,以避免意外的转换发生。

复制构造函数和移动构造函数在这个意义上并不容易“令人惊讶”。它们通常发生在预期的位置。如果您不想要它们,我希望它们被标记为 =delete 而不是显式声明。


2
实际问题是如何使用显式移动构造函数?它无法在右值上调用,所以编译器必须始终选择复制构造函数(如果可用),否则将无法编译。
编辑:这里是示例链接:http://www.ideone.com/nm7KM

@Luc:这是个好方法!也许这是唯一可以显式调用移动构造函数的方式。 - Gene Bushuyev
+1 给一个好问题,Gene :) 额外赞扬 Luc 的回答(如果您将其添加到您的帖子中以备将来参考,那将非常有用)。谢谢! - Kos

0
当从函数中返回值时,隐式移动构造函数通常可以使过程更高效。

有点离题,但是很好的观点,实际上我认为这是将移动构造函数尽可能设为内联的原因。 - Kos

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