c++ - 移动构造函数绕过复制构造函数

标签 c++ constructor

正如预期的那样,以下内容无法编译:

class A {
public:
    A() = default;
    //A(A&&) = default;
    A(const A&) = delete;
    int x;
};

int main()
{
    auto a4 = A{}; // not ok, copy constructor is deleted
    auto a5 = A(); // not ok, copy constructor is deleted
    return 0;
}

但是如果添加了移动构造函数,即使显式删除了复制构造函数,也会编译以下内容:

class A {
public:
    A() = default;
    A(A&&) = default;
    A(const A&) = delete;
    int x;
};

int main()
{
    auto a4 = A{}; // now ok, even though copy constructor is deleted
    auto a5 = A(); // now ok, even though copy constructor is deleted
    return 0;
}

为什么不考虑删除的复制构造函数?

最佳答案

Why isn't the deleted copy constructor considered?

被考虑。它只是没有被使用,所以它被删除这一事实并不重要。来自 [dcl.fct.def.delete] 的规则是:

A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: [...] If a function is overloaded, it is referenced only if the function is selected by overload resolution. [...] —end note ]

auto a = A{}; 上的重载解析(在这种情况下大括号与括号是等效的)找到两个候选构造函数:

A(const A&);
A(A&& );

选择哪个候选人是“最佳可行”候选人的规则之一来自[over.match.best]:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if [...], and then
— [...]
— the context is an initialization by conversion function for direct reference binding (13.3.1.6) of a reference to function type, the return type of F1 is the same kind of reference (i.e. lvalue or rvalue) as the reference being initialized, and the return type of F2 is not

移动构造函数是与参数相同类型的引用(右值),而复制构造函数则不是。因此,它是首选并被选为最佳可行候选者。由于重载决策未选择 A(const A&),因此我们没有引用该构造函数,因此代码没问题。

如果我们实际上使用了复制构造函数(例如 A a(a5)),that 实际上会尝试使用复制构造函数,这将是格式不正确。

关于c++ - 移动构造函数绕过复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36603628/

相关文章:

c++ - 字符串初始化失败

java - 如何在 JNI 中获取默认的 JVM INITIAL ARGS

javascript - 在 Javascript 中将两个函数引用传递给构造函数会发生错误

javascript - JavaScript 的简单继承

c++ - c++构造函数中的段错误

flutter - 如何在自定义小部件构造函数中添加和使用键

C++ std::async 在主线程上运行

std::transform_reduce 的 C++17 替代实现

c++ - 具有成员变量的 Const 对象数组 = 先前索引成员变量的总和

c++ - 使用异常抛出构造函数初始化对象的正确方法