Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 分配给匿名实例中基元类型的默认构造函数_C++_C++11 - Fatal编程技术网

C++ 分配给匿名实例中基元类型的默认构造函数

C++ 分配给匿名实例中基元类型的默认构造函数,c++,c++11,C++,C++11,考虑以下代码: #include <iostream> template<class T> void f(T& t) { t = T(); } int main() { int x = 42; f(x); std::cout << x; } #包括 模板 空f(T&T) { t=t(); } int main() { int x=42; f(x); std::cout代码中没有“默认构造函数”。只有类类型可以有构造

考虑以下代码:

#include <iostream>

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

int main()
{
    int x = 42;
    f(x);
    std::cout << x;
}
#包括
模板
空f(T&T)
{
t=t();
}
int main()
{
int x=42;
f(x);
std::cout代码中没有“默认构造函数”。只有类类型可以有构造函数。标量类型没有构造函数,默认或其他

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

对于标量类型值初始化初始化零初始化。这就是为什么代码保证输出零。抽象初始化过程的确切细节在C++语言标准版本之间发生变化,但是自从C++语言开始保证<代码>
T==int的表达式计算为零。也就是说,即使在C++98中,您的代码也将输出零

这是一个常见的误解,即所有这些
T(…)
表达式都必然暗示构造函数调用。实际上,
T(…)
表达式是一个函数强制转换表达式(无论参数的数量如何)(见语言规范中的5.2.3),它可能在某些特定情况下解析为构造函数调用,而在其他情况下与任何构造函数无关

例如,此代码

struct S { int x, y; };

S s = S();

保证用零初始化
s
(包括
s.x
s.y
),尽管类
s
有一个默认构造函数
expression仍然可以完全忽略它,而是按照自己的规则工作。

以下是关于您的问题的标准说明:

在8.5.第10段中:

初始值设定项为空括号集的对象,即(),应进行值初始化


在8.5.第7段中:

初始化T类型对象的值意味着:

  • 如果T是用户提供构造函数(12.1)的(可能是cv限定的)类类型(第9条),则 调用T的默认构造函数(如果T没有可访问的默认值,则初始化是错误的) 建造商)
  • 如果T是一个(可能是cv限定的)非联合类类型,没有用户提供的构造函数,那么对象 初始化为零,如果T的隐式声明的默认构造函数是非平凡的,则该构造函数是 打电话来
  • 如果T是数组类型,则每个元素都初始化为值
  • 否则,对象初始化为零。


因此,由于
int
甚至不是类类型,它属于上一条规则,初始化为零,因此这是一个绝对正确的行为。

基本类型没有默认构造函数。
int i;i=int()
将导致
i
为0。默认构造函数我指的是不带参数的构造函数。
int()
调用的函数是什么?(标准中此函数的名称是什么?)它称为值初始化。它是函数强制转换表示法。没有“空操作”或“未定义的行为”必需。您的结论不正确。关键是,
int
不是类类型,因此零初始化适用。这与用户提供的构造函数的存在或不存在无关。@MWid,还有“否则,对象为零初始化”部分。当然你是对的,但是你的重点有点误导。
int
初始化为零是因为第四条规则,而不是第二条规则,因为它根本不是类类型。@Christian,是的,我确实选择了一些不好的措辞,我会编辑它。你答案的第一部分是误导性的。实际发生的情况是:如果
T
是简单类型说明符(例如
int
),然后表达式
T()
创建类型为
T
的prvalue,该值已初始化。(参见5.2.3显式类型转换).8.5 10与此问题无关。因此,在上一个示例中,
S s2;
也会将
s2.x
s2.y
初始化为零?@Andrew Tomazos-Dethomling:不会。为什么它会?
S s2;
不执行值初始化,因此
s2
将包含垃圾。请注意,在C++03中在这种情况下,即使存在构造函数,也不会调用它(在这种情况下,构造函数仅为非POD类调用)。在C++11中,构造函数在概念上被调用,但由于它什么都不做,对象保持未初始化状态。也就是说,最终结果是相同的(垃圾在
s2
),但概念行为在C++03和C++11之间是不同的。这似乎有点不一致。我一直认为
T()
T;
是同一件事,只是后者被命名了——但这似乎要复杂得多。@Andrew Tomazos-深究:不,从标准化时代开始(C++98)
()
是初始值设定项的一种特殊形式。使用
()
初始值设定项与完全不使用任何初始值设定项-这是两种完全不同的情况,具有完全不同的初始化行为。
()
初始值设定项从C++98更改为C++03,从C++03更改为C++11,但其在基本情况下的功能始终相同。对于基本类型,
()
始终强制零初始化,