当我取消注释移动构造函数 A(A&&) 时,下面的代码片段会发生什么情况?
What does happen to the snippet below when I uncomment the move constructor A(A&&)?
下面的代码片段似乎没问题,我相信 main()
中的声明 A a(std::move(b).toA());
调用了 class A
的隐式声明的移动构造函数,因为 A
没有用户定义的复制构造函数,没有用户定义的复制赋值运算符,没有用户定义的移动赋值运算符,也没有用户定义的析构函数(见§ 12.8/9 N4140)。但是,当我取消注释下面的移动构造函数 A(A&&) { std::cout << "move A" << '\n'; }
时,我收到 Illegal instruction
消息。参见 live example。这是为什么?
#include <iostream>
#include <memory>
class A {
public:
// A(const A&) { std::cout << "copy A" << '\n'; }
// A(A&&) { std::cout << "move A" << '\n'; }
A(std::unique_ptr<int>&& u_ptr) : u_ptr(std::move(u_ptr)) {}
const int& getInt() { return *u_ptr; }
private:
std::unique_ptr<int> u_ptr;
};
class B {
public:
B(int u_ptr) : u_ptr(new int(u_ptr)) {}
A toA() && { return A(std::move(u_ptr)); }
private:
std::unique_ptr<int> u_ptr;
};
int main() {
B b(-1);
A a(std::move(b).toA());
std::cout << a.getInt() << '\n';
return 0;
}
您的移动构造函数定义没有执行隐式定义的定义 - 它没有移动构造 u_ptr
数据成员。所以默认构造a.u_ptr
,内部int*
初始化为nullptr
。对 a.getInt()
的调用然后尝试取消引用此 nullptr
导致崩溃。
如下定义您的移动构造函数,您的代码将正常运行
A(A&& other) : u_ptr(std::move(other.u_ptr)) { std::cout << "move A" << '\n'; }
下面的代码片段似乎没问题,我相信 main()
中的声明 A a(std::move(b).toA());
调用了 class A
的隐式声明的移动构造函数,因为 A
没有用户定义的复制构造函数,没有用户定义的复制赋值运算符,没有用户定义的移动赋值运算符,也没有用户定义的析构函数(见§ 12.8/9 N4140)。但是,当我取消注释下面的移动构造函数 A(A&&) { std::cout << "move A" << '\n'; }
时,我收到 Illegal instruction
消息。参见 live example。这是为什么?
#include <iostream>
#include <memory>
class A {
public:
// A(const A&) { std::cout << "copy A" << '\n'; }
// A(A&&) { std::cout << "move A" << '\n'; }
A(std::unique_ptr<int>&& u_ptr) : u_ptr(std::move(u_ptr)) {}
const int& getInt() { return *u_ptr; }
private:
std::unique_ptr<int> u_ptr;
};
class B {
public:
B(int u_ptr) : u_ptr(new int(u_ptr)) {}
A toA() && { return A(std::move(u_ptr)); }
private:
std::unique_ptr<int> u_ptr;
};
int main() {
B b(-1);
A a(std::move(b).toA());
std::cout << a.getInt() << '\n';
return 0;
}
您的移动构造函数定义没有执行隐式定义的定义 - 它没有移动构造 u_ptr
数据成员。所以默认构造a.u_ptr
,内部int*
初始化为nullptr
。对 a.getInt()
的调用然后尝试取消引用此 nullptr
导致崩溃。
如下定义您的移动构造函数,您的代码将正常运行
A(A&& other) : u_ptr(std::move(other.u_ptr)) { std::cout << "move A" << '\n'; }