C++ 如果我默认复制构造函数,是否会生成移动构造函数和移动赋值?

C++ 如果我默认复制构造函数,是否会生成移动构造函数和移动赋值?,c++,move-semantics,default-constructor,C++,Move Semantics,Default Constructor,对于如何最好地定义可复制但不可移动的类,我有点困惑。在我看来,删除move构造函数是一个坏主意,因为这样我就无法从临时构造函数中进行构造。另一方面,我不希望编译器隐式地为我生成一个可能错误或可能导致意外行为的移动构造函数。我的问题是是否允许编译器为以下类隐式生成移动构造函数: class C { public: int i_; C(const C&) = default; } [class.copy]/9之后: 如果类X的定义没有显式声明移动构造函数,则当且仅当

对于如何最好地定义可复制但不可移动的类,我有点困惑。在我看来,删除move构造函数是一个坏主意,因为这样我就无法从临时构造函数中进行构造。另一方面,我不希望编译器隐式地为我生成一个可能错误或可能导致意外行为的移动构造函数。我的问题是是否允许编译器为以下类隐式生成移动构造函数:

class C {
    public:
    int i_;
    C(const C&) = default;
}
[class.copy]/9之后:

如果类
X
的定义没有显式声明移动构造函数,则当且仅当

  • X
    没有用户声明的复制构造函数
  • X
    没有用户声明的复制分配运算符
  • X
    没有用户声明的移动分配运算符,并且
  • X
    没有用户声明的析构函数
[class.copy]/9之后:

如果类
X
的定义没有显式声明移动构造函数,则当且仅当

  • X
    没有用户声明的复制构造函数
  • X
    没有用户声明的复制分配运算符
  • X
    没有用户声明的移动分配运算符,并且
  • X
    没有用户声明的析构函数
如果类X的定义没有显式声明移动构造函数,则当且仅当

  • X没有用户声明的复制构造函数
  • [和……]
因为复制构造函数是用户声明的(即使它是默认的,这意味着它不是用户提供的),所以移动构造函数不会隐式声明为默认的

如果显式地
删除
移动构造函数,您将无法从临时对象中进行构造,因为删除的移动构造函数将通过重载解析进行选择。因此,对于可复制但不可移动的类,您使用的方法是正确的

如果类X的定义没有显式声明移动构造函数,则当且仅当

  • X没有用户声明的复制构造函数
  • [和……]
因为复制构造函数是用户声明的(即使它是默认的,这意味着它不是用户提供的),所以移动构造函数不会隐式声明为默认的


如果显式地
删除
移动构造函数,您将无法从临时对象中进行构造,因为删除的移动构造函数将通过重载解析进行选择。因此,您用于可复制但不可移动类的方法是正确的。

相对于您的示例,编译器将隐式声明移动构造函数,因为复制构造函数的第一个声明是默认定义。在这种情况下,复制构造函数被认为是隐式定义的。但是如果您想用以下方式更改您的类定义

class C {
    public:
    int i_;
    C(const C&);
};

C::C( const C & ) = default;

在这种情况下,编译器不会生成移动构造函数,因为复制构造函数是由用户显式声明的

相对于您的示例,编译器将隐式声明一个移动构造函数,因为复制构造函数的第一个声明是默认定义。在这种情况下,复制构造函数被认为是隐式定义的。但是如果您想用以下方式更改您的类定义

class C {
    public:
    int i_;
    C(const C&);
};

C::C( const C & ) = default;

在这种情况下,编译器不会生成移动构造函数,因为复制构造函数是由用户显式声明的

我想我误解了你的理由:/a显式删除的移动向量将通过重载解析选择。我想我误解了你的理由:/a显式删除的移动向量将通过重载解析选择。CWG1402被归类为缺陷,并被纳入clang++的最新版本中,其
-std=c++11
mode.CWG1402被归类为缺陷,并以其
-std=c++11
模式并入了clang++的最新版本中。