c++ - 缺少用户定义的构造函数是否违反了非默认可构造结构的标准?

标签 c++ visual-studio-2012 language-lawyer default-constructor aggregate-initialization

可以定义一个 struct (a) 没有用户定义的构造函数,(b) 不能为其生成默认构造函数。例如,下面的 Foo:

struct Baz
{
   Baz(int) {}
};

struct Foo
{
   int bar;
   Baz baz;
};

您仍然可以使用聚合初始化创建 Foo 的实例:

Foo foo = { 0, Baz(0) };

我的普通编译器 (VS2012) 会勉强接受这个,但它会引发 2 个警告:

warning C4510: 'Foo': default constructor could not be generated.

warning C4610: struct 'Foo' can never be instantiated - user defined constructor required

当然,我刚刚证明警告 #2 是错误的——您仍然可以使用聚合初始化来实例化它。我试过的在线编译器很乐意接受上述内容,所以我猜 VS2012 只是对这个警告过于激进。但我想确定——这段代码是否正确,或者它在技术上是否违反了标准的某些模糊部分?

最佳答案

标准明确允许像 [12.1p4] 中的 Foo 这样的情况:

[...] If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted [...] A defaulted default constructor for class X is defined as deleted if:

[...]

  • any potentially constructed subobject, except for a non-static data member with a brace-or-equal-initializer, has class type M (or array thereof) and either M has no default constructor or overload resolution (13.3) as applied to M’s default constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor

[...]

Baz 没有默认构造函数,因此上面强调的部分适用(强调我的)。

对于这种情况,没有任何“未定义”或“格式错误”的地方。隐式声明的默认构造函数被定义为已删除,仅此而已。您可以明确地做同样的事情,它仍然有效。

聚合的定义在 [8.5.1p1] 中。对于 C++14,它是:

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

“无用户提供”部分允许您对所有可能隐式声明的构造函数使用 = delete(使它们由用户声明,但不由用户提供)并且该类将仍然是一个聚合,允许您对其使用聚合初始化。

至于警告C4610,我自己和reported it之前遇到过它.如您所见,它已在即将发布的 VC++ 版本中得到修复。

可能值得一提的是,我在错误报告中使用的示例直接取自标准,在标准中被视为格式良好 ([12.2p5.4]:

struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };

这与您的情况类似,但在这里,隐式声明的默认构造函数被定义为已删除,因为该类具有引用类型的非静态成员,该引用类型没有初始化程序。

当然,这只是一个例子,但我认为这是一个额外的迹象,表明这些案例没有任何问题。

关于c++ - 缺少用户定义的构造函数是否违反了非默认可构造结构的标准?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28677593/

相关文章:

c++ - 严格别名和二进制 I/O

c++ - 鉴于 p 是一个指针是 "p > nullptr"格式正确吗?

windows - 无法使用 Visual Studio 2012 打开 .dmp 文件

mysql - 如何使用 app.config 从 vb.net 连接到 MySQL 数据库

visual-studio-2012 - Intellitrace不适用于VS 2012 Professional版本吗?

c++ - 非多态类型上的 C 风格转换

c++ - 权威的C++书籍指南和 list

c++ - 将标量 + std::array + std::tuple 转换为大元组

c++ - 全局多维数组未写入 [vs c++]

c - 用于保存函数指针的整数类型?