我删除了所有构造函数,即使随后的代码也能正常工作。如何以及为什么?
class Ax
{
public:
Ax() = delete;
Ax(Ax const&)=delete;
Ax(Ax&&)=delete;
void operator=(Ax const&)=delete;
void operator=(Ax&&)=delete;
void print()
{
cout << "Hello \n";
}
};
int main(int argc, char** argv)
{
Ax{}.print();
return 0;
}
(有关此主题的完整演练,请参阅博客文章The Fckle汇总)
类Ax
是C ++ 11,C ++ 14和C ++ 17中的聚合,因为它没有用户提供的构造函数,这意味着Ax{}
是聚合初始化,绕过了任何用户声明的构造函数,甚至是删除的构造函数。
struct NonConstructible {
NonConstructible() = delete;
NonConstructible(const NonConstructible&) = delete;
NonConstructible(NonConstructible&&) = delete;
};
int main() {
//NonConstructible nc; // error: call to deleted constructor
// Aggregate initialization (and thus accepted) in
// C++11, C++14 and C++17.
// Rejected in C++20 (error: call to deleted constructor).
NonConstructible nc{};
}
什么是聚合类的定义已通过各种标准版本(从C ++ 11到C ++ 20)进行了更改,这些规则可能会产生令人惊讶的后果。从C ++ 20开始,尤其是由于实施
解决了大多数通常令人惊讶的聚合行为,特别是不再允许聚合具有用户声明的构造函数,这比仅禁止用户提供的构造函数更严格地要求类成为聚合。
请注意,提供显式默认(或已删除)的定义作为用户提供的构造函数进行离线计数,这意味着在以下示例中,B
具有用户提供的默认构造函数,而A
没有:
struct A {
A() = default; // not user-provided.
int a;
};
struct B {
B(); // user-provided.
int b;
};
// Out of line definition: a user-provided
// explicitly-defaulted constructor.
B::B() = default;
结果A
是一个聚合,而B
不是。反过来,这B
意味着通过空的direct-list-init初始化将导致其数据成员b
处于未初始化状态。A
但是,对于,相同的初始化语法将导致(通过A
对象的聚合初始化以及其数据成员a的后续值初始化)其数据成员的零初始化a
:
A a{};
// Empty brace direct-list-init:
// -> A has no user-provided constructor
// -> aggregate initialization
// -> data member 'a' is value-initialized
// -> data member 'a' is zero-initialized
B b{};
// Empty brace direct-list-init:
// -> B has a user-provided constructor
// -> value-initialization
// -> default-initialization
// -> the explicitly-defaulted constructor will
// not initialize the data member 'b'
// -> data member 'b' is left in an unititialized state
这可能会令人惊讶,并且具有读取未初始化数据成员的明显风险,并带有b
未定义行为的结果:
A a{};
B b{}; // may appear as a sound and complete initialization of 'b'.
a.a = b.b; // reading uninitialized 'b.b': undefined behaviour.
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句