提问人:CPPL 提问时间:6/6/2022 更新时间:6/6/2022 访问量:977
“隐式删除”构造函数 =delete 还是根本没有声明?[复制]
Is "implicitly deleted" constructor =delete or not declared at all? [duplicate]
问:
给定以下玩具代码:
class X
{
public:
X() { }
X(const X&) { }
//X(X&&) = delete;
};
int main()
{
X x;
X y = std::move(x);
}
我知道在这种情况下它被隐式删除,因为作为用户声明的构造函数存在。但我对这里术语“隐式删除”的含义有点困惑:如果我们取消注释,代码的行为会有所不同,这意味着隐式删除和“显式”删除之间存在差异。X::X(X&&)
X(const X&)
X(X&&) = delete;
在我的脑海中,有两种不同的理解:
“隐式删除”意味着编译器生成一些类似于的代码(也就是说,编译器知道有并且它知道它被删除了),但生成的代码与尝试调用时的不同之处在于,编译器选择而不是报告错误。(已取消注释,编译器将不会选择并报告错误)
X(X&&) = delete;
X(X&&)
X(X&&)
X(X&&) = delete;
X y = std::move(x);
X::X(X&&)
X(const X&)
X(X&&) = delete;
X(const X&)
“隐式删除”意味着根本没有在类中声明,换句话说,编译器没有任何关于 的信息,因此直接匹配到 。
X(X&&)
X(X&&)
X y = std::move(x);
X(const X&)
请问我的哪一种理解是正确的?
我的猜测是前者应该是正确的。因为如果我们按如下方式更改上面的代码:
class X
{
public:
X() { }
//X(const X&) { }
X(X&&) {}
};
int main()
{
X x;
X y = x;
}
我们得到一个错误,这意味着编译器知道它何时被隐式删除。'X::X(const X &)': attempting to reference a deleted function
X(const X &)
然而,对我来说,我的后一种理解似乎是一种更直接的完成工作的方式。所以我想知道我们为什么要设计“隐式删除”的概念(这也让我有点不一致的感觉,因为“隐式删除”需要与“显式删除”不同的行为)
答:
当您取消注释时,您正在做的是将该 ctor 声明为已删除。例如,这意味着它确实参与了重载解析,在 的情况下,它赢了,但实际上不能使用,因为它缺少主体。X(X&&) = delete;
X y = std::move(x);
请注意,这并不特别适用于(特殊或非)成员函数,而是适用于一般函数:
#include<iostream>
// this is akin to defining both copy and move ctor
auto f(int) { std::cout << "int" << std::endl;}
auto f(double) { std::cout << "double" << std::endl;}
// this is akin to defining copy ctor and deleting move ctor
auto g(int) { std::cout << "int" << std::endl;}
auto g(double) = delete;
// this is akin to defining only copy ctor
auto h(int) { std::cout << "int" << std::endl;}
// auto h(double) is not even delcared
int main() {
f(1);
f(1.2);
g(1);
//g(1.2); // compile time error
h(1);
h(1.2); // round error
}
特定于特殊成员函数的是声明/定义/ing/ing/不写入一个函数如何影响另一个函数。default
delete
本页解释了所有内容,但需要非常仔细的阅读。
这里有一个棘手的点(我的粗体):
删除了隐式声明的移动构造函数
如果满足以下任一条件,则类的隐式声明或默认移动构造函数定义为已删除:
T
- T 具有无法移动的非静态数据成员(已删除、无法访问或不明确的移动构造函数);
- [...]
[...]
以上是什么意思?
下面是一个示例:
// copyable but not movable
struct CNM {
CNM() {};
CNM(CNM const&) = default;
CNM(CNM&&) = delete;
};
struct W {
W() {}
W(W&&) = default; // defaulted... but actually deleted!
CNM nm;
};
W w1;
W w2{std::move(w1)}; // compile time error
评论
g(double) = delete
h(double)
评论
X(X&&) = delete;
X(X&&) = delete(intentional);