在什么情况下我应该明确需要实现移动构造函数和移动赋值运算符?

Joh*_*ell 16 c++ optimization move-semantics c++11

鉴于一个类实际上是可移动的,手动实现移动构造函数和移动类的赋值运算符很快变得乏味.

我想知道什么时候这样做实际上是一个沉重,沉重,过早的优化?

例如,如果一个类只有普通的POD数据或者它们自己有移动构造函数和移动赋值运算符定义的成员,那么我猜测编译器将只是优化该批次的狗屎(在POD的情况下)和否则使用成员的移动构造函数和移动赋值运算符.

但这有保证吗?在什么情况下,我应该想到明确需要实现一个移动构造函数和移动赋值操作符?

编辑:正如他在回答评论下面提到的尼科尔流星锤/sf/answers/697627381/,与Visual Studio 11 Beta版(之前)没有转移构造函数或移动赋值操作符是不断自动生成.参考:http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

How*_*ant 9

如果你发现自己实施,任何:

  • 析构函数
  • 复制构造函数
  • 复制作业

然后你应该问自己是否需要实施移动构造.如果您"=默认"上述任何一项,您应该问自己是否应该"=默认"移动成员.

更重要的是,您应该记录并测试您的假设,例如:

static_assert(std::is_nothrow_default_constructible<A>::value, "");
static_assert(std::is_copy_constructible<A>::value, "");
static_assert(std::is_copy_assignable<A>::value, "");
static_assert(std::is_nothrow_move_constructible<A>::value, "");
static_assert(std::is_nothrow_move_assignable<A>::value, "");
static_assert(std::is_nothrow_destructible<A>::value, "");
Run Code Online (Sandbox Code Playgroud)

  • @MatthieuM.:我相信你指的是http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1402,它目前处于就绪状态.这意味着它还不是官方的,但可能会在今年秋季投票成一份工作草案.此更改将意味着移动成员不会像现在那样经常被隐式删除.我认为这是一个非常好的变化.但是这种变化也是我强调static_assert测试的动机的一部分.在每个人学习新规范和规范本身是一个移动目标之间,我们生活在困难时期.测试,测试,测试. (3认同)

Xeo*_*Xeo 8

首先,移动语义只对包含任何类型资源的类有帮助."扁平"课程根本无法从中受益.

接下来,你应该建立你的班列"积木"一样的vector,unique_ptr和喜欢,所有的处理资源的事实真相低层次的细节.如果您的类是这样完成的,那么您将不必编写任何内容,因为编译器将为您正确生成成员.

如果你需要为日志记录编写析构函数,那么移动ctors的生成将被禁用,因此你需要一个T(T&&) = default;支持它的编译器.否则,这是自己写这样一个特殊成员的唯一地方之一(好吧,除非你写这样一个"积木").

请注意,析构函数和构造函数中的日志记录可以更简单地完成.只需继承一个记录构造/销毁的特殊类.或者使它成为成员变量.接着就,随即:

tl; dr让编译器为您生成特殊成员.这也算复制构造函数和赋值运算符,以及析构函数.不要自己写那些.

(好吧,也许是赋值操作符,如果你可以将它们识别为瓶颈并想要优化它们,或者如果你想要特殊的异常安全或者某些东西.虽然,"构建块"应该已经提供了所有这些.)