值初始化是否使用隐式默认构造函数?

Fox*_*942 1 c++ constructor aggregate list-initialization c++17

根据这个网站/链接/:

如果显式声明默认构造函数但将其标记为已删除,则不能使用空大括号初始化:

它还给出了一个例子:

class class_f {
public:
    class_f() = delete;
    class_f(string x): m_string { x } {} // if it is deleted, there will be no errors.
    string m_string;
};

int main()
{
    class_f cf{ "hello" };
    class_f cf1{}; // compiler error C2280: attempting to reference a deleted function
}
Run Code Online (Sandbox Code Playgroud)

我真正不明白的是,如果没有用户提供的构造函数,即使删除的默认构造函数仍然存在,也不会再出现错误。据我所知,如果有用户提供的构造函数,就不会存在隐式的默认构造函数,但默认构造函数已经被删除了。所以我不知道在值初始化的情况下调用什么以及为什么它在下面的示例中起作用:

#include <string>

class class_f {
public:
    class_f() = delete;
    std::string m_string;
};
int main()
{
    class_f cf1{}; // Does the implicit-default constructor is called here? But, it is deleted or not?
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*cow 5

根据聚合的定义,C++ 17 标准和 C++ 20 标准之间存在差异。

\n

根据 C++ 17 标准此声明

\n
class class_f {\npublic:\n    class_f() = delete;\n    std::string m_string;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

声明一个可以使用大括号初始化的聚合。

\n

来自 C++ 17 标准(11.6.1 聚合)

\n
\n

1 聚合是一个数组或一个类(第 12 条)

\n

(1.1) \xe2\x80\x94没有用户提供的、显式的或继承的构造函数\n(15.1),

\n

(1.2) \xe2\x80\x94 没有私有或受保护的非静态数据成员(第 14 条),

\n

(1.3) \xe2\x80\x94 无虚函数 (13.3),以及

\n

(1.4) \xe2\x80\x94 没有虚拟、私有或受保护的基类 (13.1)。

\n
\n

根据 C++ 20 标准,此声明不声明聚合,编译器将发出与对象初始化相关的错误。

\n

来自 C++ 20 标准(9.4.2 聚合)

\n
\n

1 聚合是一个数组或一个类(第 11 条)

\n

(1.1) \xe2\x80\x94没有用户声明或继承的构造函数(11.4.5),

\n

(1.2) \xe2\x80\x94 没有私有或受保护的直接非静态数据成员 (11.9),

\n

(1.3) \xe2\x80\x94 无虚函数 (11.7.3),以及

\n

(1.4) \xe2\x80\x94 无虚拟、私有或受保护的基类 (11.7.2)。

\n
\n

您可以尝试下面的演示程序

\n
#include <iostream>\n#include <iomanip>\n#include <type_traits>\n\nclass class_f {\npublic:\n    class_f() = delete;\n    std::string m_string;\n};\n\nint main()\n{\n    std::cout << "std::is_aggregate_v<class_f> = " <<\n        std::boolalpha << std::is_aggregate_v<class_f> << '\\n';\n}\n
Run Code Online (Sandbox Code Playgroud)\n

运行它,设置编译器选项以支持 C++ 17,然后支持 C++ 20。

\n

类型特征std::is_aggregate是在 C++ 17 中引入的。

\n