删除移动构造函数时大括号初始化

Aza*_*hli 0 c++ c++20 gcc11

这可能不是 C++20 特有的,但这就是我现在正在使用的。我有一个简单的结构

\n
struct foo {\n    int bar;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

可以声明并初始化为

\n
const auto baz = foo{42};\n
Run Code Online (Sandbox Code Playgroud)\n

现在,当我禁用移动构造函数 ( foo(foo&&) = delete;) 时,上述初始化失败并显示

\n
\n

错误:没有匹配的函数可调用 \xe2\x80\x98foo::foo()\xe2\x80\x99

\n
\n

出现此错误的原因是什么?有没有办法恢复默认行为?

\n

use*_*522 5

它特定于 C++20。自 C++20 起,如果类根本没有任何用户声明的构造函数,则该类不再是聚合的,即使它只是默认或删除。聚合初始化将不再起作用。

这是向后兼容性的重大更改,您无法真正恢复旧的行为。您必须根据更改调整您的代码。

如果要禁用移动构造函数,则需要添加一个适当的构造函数来用于初始化,即采用一个int作为参数并bar用它进行初始化的构造函数,并且您不能再依赖聚合初始化。或者,您可以添加具有默认初始值设定项的不可移动成员作为类的最后一个成员。那么就不需要在聚合初始化中提供初始化程序,但会使整个类不可移动。

然而,有点令人惊讶的是,您需要手动禁用移动构造函数。如果类是聚合的,没有任何声明的构造函数,当且仅当其所有内容都是可移动的时,它才是可移动的。这通常应该是预期的行为,因为聚合类只是将各个成员集中在一起,而不添加任何其他类不变量。