编译器不生成移动构造函数

mad*_*adu 10 c++ move-semantics c++11

我试图理解移动语义正在寻找编译器生成的移动构造函数(复制和赋值).在Modern Effective C++中,Scott Meyers在第17项中说,如果没有声明显式的复制构造函数,编译器将生成移动构造函数,它将为non-static成员执行成员移动.

为了确认这一点,我正在尝试下面的代码:

#include <iostream>
#include <string>
using namespace std;

class A
{
private:
    std::string str;

public:

    A() : str("Init string")
    {
        cout << "Default constructor" << endl;
    }

    A(std::string _str) : str(_str)
    {
        cout << "Constructor with string" << endl;
    }

    std::string getString()
    {
        return str;
    }
};

int main() {

    A obj1;
    A obj2("Obj2 string");

    cout << endl;
    cout << "obj1: " << obj1.getString() << endl;
    cout << "obj2: " << obj2.getString() << endl;

    obj1 = std::move(obj2);

    cout << endl;
    cout << "obj1: " << obj1.getString() << endl;
    cout << "obj2: " << obj2.getString() << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2: Obj2 string
Run Code Online (Sandbox Code Playgroud)

但我预计它会是:

Default constructor
Constructor with string

obj1: Init string
obj2: Obj2 string

obj1: Obj2 string
obj2: 
Run Code Online (Sandbox Code Playgroud)

因为obj2.str会被移动,现在有一个空字符串.

编译器没有生成移动赋值构造函数并调用复制赋值运算符的原因是什么?

编辑: 如下所示实现移动赋值运算符给出预期输出(即调用std :: move后的空字符串)

A& operator=(A&& obj)
    {
        cout << "Move assignment operator" << endl;
        str = std::move(obj.str);
        return *this;
    }
Run Code Online (Sandbox Code Playgroud)

son*_*yao 7

首先,obj1 = std::move(obj2);调用赋值运算符,因此它与构造函数无关.

是,编译器为其生成移动赋值运算符A,该运算符执行成员移动操作,包括数据成员str.问题是移动操作后str处于有效但未指定的状态.另见std::basic_string::operator=.

将内容替换为str使用移动语义的内容.str之后处于有效但未指定的状态.

我认为你可能只会观察到相同的结果std::string,例如

std::string str1 = "Init string";
std::string str2 = "Obj2 string";
str1 = std::move(str2);
std::cout << str2;
Run Code Online (Sandbox Code Playgroud)

与铿锵生活,仅供参考; 它会按预期给出结果,但仍记得结果未指定.