显式移动构造函数?

Posted

技术标签:

【中文标题】显式移动构造函数?【英文标题】:Explicit move constructor? 【发布时间】:2011-10-09 04:17:45 【问题描述】:

所有大多数构造函数推荐使用explicit关键字,这些构造函数可以用一个参数调用,除了复制构造函数。

对于复制构造函数,它有一个用途(禁止通过函数调用、返回等进行隐式复制),但这不是通常想要的。

移动构造函数呢?是否有任何合理的用例来明确它们?这里有什么好的做法?

【问题讨论】:

“复制构造函数”和“可以用一个参数调用的构造函数”有什么区别?我只是对 DeadMGs 的答案感到困惑,因为我认为这些是同一回事。这 is 只是它的使用方式,并且(除了“显式”)不是构造函数的声明方式,是吗?还是我疯了? @Steve314:单参数复制构造函数具体是构造函数T([const] [volatile] T&)。 12.8/2。 T(int) 是一个可以用一个参数调用的构造函数,但不是复制构造函数,因为它不会“复制”T 的实例。 @Steve Jessop - 是的,当然。显然我已经脑死亡了。 感谢您的回答!那么我们是否可以同意没有合理的(即以明显的方式有益的)理由来明确说明? 也推荐用于在 C++0x 中只能为多个参数调用的构造函数。 【参考方案1】:

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

【讨论】:

有点题外话,但其实很好——我认为如果可能的话,这是让移动构造函数内联的原因。【参考方案2】:

实际的问题是如何使用显式移动构造函数?它无法在右值上调用,因此编译器必须始终选择一个复制构造函数(如果可用),否则编译失败。

编辑:这里是示例的链接:http://www.ideone.com/nm7KM

【讨论】:

@Luc:这很好!并且可能是唯一可以调用显式移动构造函数的方法。 +1 提出了一个好问题,Gene :) 为 Luc 提供了更多答案(如果您将其添加到您的帖子中以供将来参考,这可能会很有用)。谢谢!【参考方案3】:

建议将explicit 关键字用于(单参数)converting 构造函数,以避免在意想不到的地方发生意外的转换。

从这个意义上说,复制构造函数和移动构造函数并不“令人惊讶”。它们主要发生在预期的地方。如果您不想要它们,我希望它们被标记为 =delete 而不是明确的。

【讨论】:

【参考方案4】:

explicit 移动构造函数会影响与例如的兼容性。标准算法。例如,std::swap<T> 要求 T 是 MoveConstructible。反过来,MoveConstructible 是根据表达式指定的,即T u = rv;(其中rvT 类型的右值)。

如果给定类型既没有非显式复制构造函数也没有非显式移动构造函数,则T u = rv; 无效并且该类型不能与std::swap 一起使用。 (然而,在这个特定的例子中,可以专门化 std::swap 以提供所需的功能,例如通过使用 T u(rv);)。

更简单地说,explicit 移动或复制构造函数违背预期,不能与通用代码一起使用。

标准库的其他一些提出 MoveConstructible 要求的部分:

unique_ptr<T, D>的删除者 调用包装器,用于例如bind(所有传递的衰减类型都关心) threadasynccall_once(均在调用包装器方面指定) sort, stable_sort, nth_element, sort_heap

【讨论】:

【参考方案5】:

您可能需要一个隐式移动构造函数用于大多数用途。它们通常与复制构造函数属于同一类别。 all 单参数构造函数不建议使用显式,但大多数情况下建议使用。移动构造函数不在该列表中。

【讨论】:

以上是关于显式移动构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

当我将构造函数作为参数显式调用时,不会调用移动构造函数

c++类的构造函数不显式声明会自动生成吗

编译器何时不生成移动构造函数和移动赋值?

隐式超级构造函数 Person() 未定义。必须显式调用另一个构造函数?

构造函数必须显式初始化没有默认构造函数的成员

C++中派生类的构造函数怎么显式调用基类构造函数?