移动构造函数是隐式的吗? [英] Can a move constructor be implicit?

查看:128
本文介绍了移动构造函数是隐式的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的类:

  class A 
{
public:
std :: string field_a;
std :: string field_b;
}

现在考虑以下副本构造:

  A a1(a2); 

复制结构将充分复制 A 缺少一个显式的拷贝构造函数,因为 std :: string 的拷贝构造函数将被编译器生成的隐式拷贝构造函数调用。


$



编辑:测试此处显示:

  A a2(std :: move(a1)); 

实际上会导致复制构造,除非特定的move构造函数:

  A(A&& other):a(std :: move(other.a)){} 



已定义。



EDIT EDIT
我ping了Stephan T Lavavej,问他为什么VC 2012似乎不遵循12.8中关于隐式移动构造函数生成的草案。他很善良地解释:


这更像是一个功能尚未实现比一个错误。 VC目前
实现我所谓的右值引用v2.0,其中move
ctors / assigns绝不会隐式生成,永远不会影响
隐式生成复制ctors / assigns。 C ++ 11指定rvalue
引用v3.0,这是您正在查找的规则。



解决方案

是的,从C ++ 11草案,12.8:


如果类X的定义没有明确声明一个移动构造函数,当且仅当




    时,会隐式声明
    为默认值 X没有用户-declared copy constructor,
  • X没有用户声明的复制赋值运算符,

  • X没有用户声明的,

  • X没有用户声明的析构函数,

  • move构造函数不会被隐式定义为已删除。


后面的条件指定更多细节:


隐式声明的复制/移动构造函数是其类的内联公共成员。如果X具有:




  • 一个类的X的默认复制/移动构造函数定义为已删除非平凡的相应构造函数,X是类似union的类,

  • 类型为M(或其数组)的非静态数据成员不能被复制/移动,因为$ b $如果应用于M的相应构造函数,则b重载分辨率(13.3)导致从默认构造函数中删除或不可访问的模糊度或
    函数。

  • 直接或虚拟不能被复制/移动的基类B,因为重载分辨率(13.3)作为
    应用于B的相应构造函数导致模糊性或被删除的函数或
    不能从默认构造函数访问, li>
  • 任何直接或虚拟基类或非静态数据成员,其类型的析构函数被删除
    或从默认构造函数无法访问

  • 为复制构造函数,右值引用类型的非静态数据成员,或

  • 用于移动构造函数,非静态数据成员或直接或虚拟基类

很明显,移动构造函数将被隐式声明为:


  1. 该类没有用户声明的任何其他特殊成员函数。

  2. 移动构造函数可以通过移动其所有成员和基数来实现。

您的类显然符合这些条件。


Consider the following class:

class A
{
public:
   std::string field_a;
   std::string field_b;
}

Now consider the following copy construction:

A a1(a2);

The copy construction will adequately copy A despite the lack of of an explicit copy constructor because the copy constructors for std::string will be called by the compiler generated implicit copy constructor.

What I wish to know is, is the same true for move construction?

EDIT: Testing here shows that:

A a2(std::move(a1));

Will actually result in a copy construction, unless the specific move constructor:

A( A && other ) : a(std::move(other.a)) {}

Is defined.

EDIT EDIT I pinged Stephan T Lavavej and asked him why VC 2012 doesn't seem to follow what draft 12.8 states regarding implicit move constructor generation. He was kind enough to explain:

It's more of a "feature not yet implemented" than a bug. VC currently implements what I refer to as rvalue references v2.0, where move ctors/assigns are never implicitly generated and never affect the implicit generation of copy ctors/assigns. C++11 specifies rvalue references v3.0, which are the rules you're looking at.

解决方案

Yes, from the C++11 draft, 12.8:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator,
  • X does not have a user-declared destructor, and
  • the move constructor would not be implicitly defined as deleted.

The latter condition is specified with more detail later:

An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:

  • a variant member with a non-trivial corresponding constructor and X is a union-like class,
  • a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
  • a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
  • any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
  • for the copy constructor, a non-static data member of rvalue reference type, or
  • for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.

Plainly speaking, the move constructor will be implicitly declared if:

  1. The class does not have user-declared any of the other special member functions.
  2. The move constructor can be sensibly implemented by moving all its members and bases.

Your class obviously complies with these conditions.

这篇关于移动构造函数是隐式的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆