当我取消注释移动构造函数 A(A&&) 时,下面的代码段会发生什么?

What does happen to the snippet below when I uncomment the move constructor A(A&&)?

本文关键字:代码 什么 段会发 注释 取消 移动 构造函数      更新时间:2023-10-16

下面的代码片段似乎是对的,我相信main()中的声明A a(std::move(b).toA());调用了隐式声明的移动构造函数A类,因为A没有用户定义的复制构造函数,它没有用户定义的复制赋值操作符,它没有用户定义的移动赋值操作符,也没有用户定义的析构函数(参见§12.8/9 N4140)。然而,当我取消下面的移动构造函数A(A&&) { std::cout << "move A" << 'n'; }的注释时,我收到Illegal instruction消息。参见实际示例。为什么会这样?

#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;
}

您的move构造函数定义没有执行隐式定义的操作—它不会移动u_ptr数据成员的构造。因此,a.u_ptr是默认构造的,内部int*初始化为nullptr。然后,对a.getInt()的调用试图解引用这个nullptr,从而导致崩溃。

定义你的move构造函数如下所示,你的代码将正确运行

A(A&& other) : u_ptr(std::move(other.u_ptr)) { std::cout << "move A" << 'n'; }