gpt4 book ai didi

c++ - 该片段在 Coliru 中编译时带有警告,但在 Ideone 中编译正常。哪一个是正确的?

转载 作者:可可西里 更新时间:2023-11-01 15:39:27 25 4
gpt4 key购买 nike

此代码在 Coliru 中编译时带有警告 [unitialized members a[1].ia[2].istd::cout << main() 中的表达式] 但在 Ideone 中正常编译.

#include <iostream>

struct A
{
int i;
A(int j) : i{j} {};
A() = default;
};

int main() {
A a[3] = { A(1) };
std::cout << a[1].i << ' ' << a[2].i << '\n';
}

根据我对 iso § 8.5 p7 的解释,Ideone 是正确的,因为该条款中的第 4 个要点。

这是来自 N3797 的 § 8.5 p7

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;
  • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized.

An object that is value-initialized is deemed to be constructed and thus subject to provisions of this International Standard applying to “constructed” objects, objects “for which the constructor has completed,” etc., even if no constructor is invoked for the object’s initialization.

最佳答案

就 C++14 (N3797) 而言,Ideone 是正确的(参见 Casey 对 C++11 的回答),因为 a[1]a[2]A{}初始化,也就是值初始化,导致i为0。这来自N3797 § 8.5.1/7:

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal initializer, from an empty initializer list (8.5.4). [ Example:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };

initializes ss.a with 1, ss.b with "asdf", ss.c with the value of an expression of the form int{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, ’s’)

根据 § 8.5.1/1,数组是聚合(聚合是数组...),因此这适用于数组的初始化。

表达式 T{}(一个空的初始化列表)根据 § 8.5.4/3 对对象进行值初始化:

Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

我们可以根据 § 8.5/8 确认值初始化使 i 的值为 0:

If T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

根据 § 8.4.2/4,您的类没有用户提供的默认构造函数:

A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.

值得注意的一点是,如果您的默认构造函数是用户提供的并且未初始化 i,则将使用 8.5/8 的第一个点和 i将保持未初始化状态,如您在此 example 中所见.

最后,关于比较的小说明。 Ideone 使用几个不同版本的 GCC。使用哪一个会有所不同(如果需要,您可以使用 __VERSION__ 检查)。在这种情况下,编译器标志也略有不同。如果 -std=c++1y 存在(我不知道除了使用附加功能之外的检查方法),会有一些 C++14 支持,但不完整支持,所以小的变化(T{}T(),从大括号或相等初始化器初始化并检查默认初始化的语义约束)可能无法实现。事实上,你甚至可以check the first . Coliru 允许您配置构建命令,所以仅仅说 Coliru 是非常含糊的。

无论哪种方式,在出现足够的 C++14 支持(或至少在它标准化之前)之前,使用 N3797 测试一致性行为都不太值得。在这种情况发生之前,我倾向于坚持使用 N3485。在这个具体示例中,我认为这两个标准的行为之间没有任何区别。请查看 Casey 的回答,了解这两个标准在这个问题上有何不同。你有一个转换构造函数,所以你的对象将在 C++11 中默认初始化。

关于c++ - 该片段在 Coliru 中编译时带有警告,但在 Ideone 中编译正常。哪一个是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20936574/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com