如果我不声明移动构造函数,则会调用复制构造函数,但如果我删除移动构造函数 - 编译错误 - 为什么?

问题描述 投票:0回答:1
struct X
{
    X() = default;
    
    X(const X& src)
    {
        cout << "copy" << endl;
    }
};

int main()
{
    X x1;
    
    X x2(move(x1));
}

输出: 复制

struct X
{
    X() = default;
    
    X(const X& src)
    {
        cout << "copy" << endl;
    }
    
    X(X&& src) = delete;
};

int main()
{
    X x1;

    X x2(move(x1));
}

编译错误:

error: use of deleted functionX::X(X&&)28 |     X x2(move(x1));
      |                  ^

所以我很困惑。当我没有编写移动构造函数时 - 看起来它没有生成移动构造函数,因为它调用了我的复制构造函数。但是为什么当我显式删除第一个动作时却报错呢?

c++ move copy-constructor default-constructor move-constructor
1个回答
1
投票

将重载定义为

delete
not 意味着“此重载不存在”。这意味着“这个重载存在,但尝试调用它是一个错误。”

int foo(double) { return 1; }
// there is no foo(int) at all
int const x = foo(int(5)); // compiles fine: chooses foo(double) overload

int bar(double) { return 2; }
int bar(int) = delete;
int const y = bar(int(5)); // error! chose bar(int) over bar(double) but bar(int) = delete

如果您没有在类中声明移动构造函数,但声明/定义了复制构造函数,那么您所写的正是您得到的。你的第一个

X
的构造函数有两个重载
X::X()
X::(X const&)
,就是这样。然后,您可以使用
X
xvalue(即引用现有对象的右值)来调用它。右值(包括 xvalues)can 绑定到
const&
引用,因此在
X::(X const&)
中选择
main
重载,并且您的代码可以正常编译。

如果您添加

X::X(X&&) = delete;
,那么您所写的就是您得到的。
X
现在有一个移动构造函数(声明了重载
X::(X&&)
),但调用它是一个错误。右值 更喜欢绑定到 &&
 引用而不是 
const&
 引用,因此 
main
 现在尝试调用 
X::X(X&&)
 而不是 
X::X(const X&)
 并且失败。

(有时候,你写的并不是你得到的。最重要的是,如果你既不写复制构造函数,也不写移动构造函数,也不写赋值函数,也不写析构函数,那么编译器会声明所有 5 个。这启用了零规则:更喜欢写根本不需要自定义特殊函数的类,其中编译器生成的函数已经是正确的。)

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.