C++ 11:分配给匿名实例的基本类型的默认构造函数

And*_*zos 9 c++ c++11

请考虑以下代码:

#include <iostream>

template<class T>
void f(T& t)
{
    t = T();
}

int main()
{
    int x = 42;
    f(x);
    std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)

C++ 11标准是否定义了输出是什么?我的编译器输出0,但我的印象是原始类型的默认构造函数是空操作或未定义的行为.

AnT*_*AnT 18

您的代码中没有"默认构造函数".只有类类型可以有构造函数.标量类型没有构造函数,默认或其他.

T()语法创建通过所谓的初始化的临时对象的值初始化.值初始化仅针对类型解析为构造函数调用,并且仅针对具有用户定义构造函数的构造函数调用(在C++ 11中具有一些细微差别).对于其他类型,值初始化根本不涉及任何构造函数.它根据其自己的特定且相当精细的初始化规则进行,这些规则直接定义数据的初始值,而不涉及任何构造函数(参见语言规范中的8.5).

对于标量类型,值初始化执行零初始化.这就是为什么您的代码保证输出零的原因.抽象初始化过程的确切细节在C++语言标准版本之间发生了变化,但是自从C++语言开始时,C++语言保证T()表达式被T == int评估为零.即使在C++ 98中,您的代码也会输出零.

一种常见的误解是,所有这些T(...)表达式在某种程度上都必然意味着构造函数调用.实际上,T(...)expression是一个函数强制转换表达式(无论参数的数量是多少)(参见语言规范中的5.2.3),它可能会在一些狭窄的特定情况下解析为构造函数调用,并且与任何构造函数无关.其他情况.

例如,这段代码

struct S { int x, y; };

S s = S();
Run Code Online (Sandbox Code Playgroud)

保证初始化s用零(即两个s.xs.y尽管这个类将是零)S有一个默认的构造函数不执行任何操作.我特意提出这个例子来说明这样一个事实,即使在默认构造函数存在的情况下,T()表达式仍然可以完全忽略它,而是按照自己的规则工作.