11

为什么为什么当其他构造函数存在时,“ctor()= default”更改行为?

struct wrapper 
{ 
    explicit wrapper(void *); 
    wrapper() = default; 
    int v; 
}; 

int main() { return wrapper().v; } // You should run this in Debug mode 

回报0xCCCCCCCC,而

struct wrapper { wrapper() = default; int v; }; 
int main() { return wrapper().v; } 

struct wrapper { int v; }; 
int main() { return wrapper().v; } 

都返回0

+1

当您添加非默认构造函数时,类型不再是聚合。我相信这是在玩这个,不知道如何。无论如何,我怀疑你保证它是0。 –

+0

@RyanHaining:你确定吗?如果是这样的话,这似乎很奇怪,因为这意味着只有当你没有其他构造函数时才可以使用'= default',这似乎毫无意义...... – Mehrdad

+0

'= default'将返回默认的构造函数,但在这两种情况下'v'都是非空间化的。有了gcc,即使在第一种情况下,我也能得到0,但这只是偶然。 –

回答

4

值初始化,如果T是无需用户提供的或删除的缺省-构造函数的类型,则该对象是零初始化(第8.5节/ 8.2)。 wrapper的确如此。

你的第一示例实现零初始化(第8.5节/ 6.1,重点煤矿)

第三壳体相匹配 - 如果T是标量类型(3.9),该对象被初始化为值通过将整数文字 0(零)转换为T而获得;

- 如果T是一个(可能是cv限定的)非联合类类型,则每个非静态数据成员和每个基类子对象都被初始化并且填充被初始化为零位;

- 如果T是一个(可能CV修饰)联合类型,对象的第一非静态命名的数据成员是零初始化和填充被初始化为零比特;

- 如果T是一个数组类型,每一个元素是零初始化

- 如果T是引用类型,则执行

在第一示例

所以没有初始化,v应被初始化为零。这看起来像一个错误。

在你的第二个和第三个例子中,你不再有用户提供的构造函数,但是你有一个非用户提供或删除的默认构造函数,所以你的例子仍然属于第零个初始化,它是对每个非静态数据成员进行零初始化。 VS在那里是正确的。

+0

C++ 11标准中存在缺陷。如果你阅读IS,它会说“没有用户提供的构造函数”,它缺少关键的“默认”。 – dyp

+0

@dyp:什么是“IS”? – Mehrdad

+6

@Mehrdad:噢,最近已经变得暧昧了 - 我指的是国际标准。另请参阅:http://open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1301 – dyp

4

这似乎确实是MSVC中的一个错误。在所有三种情况wrapper无用户提供默认的构造,所以初始化与wrapper()调用:

(所有的n3690引文)

(8.5/11),它的初始值设定的目标是一空的圆括号,即(),应进行数值初始化。

(感谢DYP),这将导致int v零intialization

初始化然后指我们的规则:

(8.5/8)如果T是一个(可能cv-qualified)类的类型,没有用户提供或删除的默认构造函数,那么该对象将被初始化并检查默认初始化的语义约束。

零初始化规则状态:

(8.5/6)如果T是一个(可能CV修饰)非工会类型,每个非静态数据成员,并且每个基础类子对象零初始化和填充被初始化为零位

int v是的wrapper数据成员根据为零initialiazed本身:

(8.5/6)如果T是一个标量类型(3.9),该对象被初始化为通过转换整数文字而得到的值0(零)到T

哪个不是你观察行为。

+0

如果你能解释为什么GCC和Clang正在经历额外的麻烦,如果你认为VC++是正确的而不是这样做的话,那么就会初始化所有的东西。 – Mehrdad

+0

@Mehrdad我翻转了所有的东西 –

+0

@dyp这是我曾经(推到)击中的最微妙的C++点。 –

相关问题