考虑这段代码:
int main()
{
int i(6); //this will result in i==6,but consider next initializations
int j(int());
T * p2 = new T();
}
我发现 的值为j
1,但这应该是 0,因为int()
它是一个值等于 0 的临时值。
此外,运算符的语法new
是new typename
,但这里T()
将是一个临时对象而不是类型名称。
考虑这段代码:
int main()
{
int i(6); //this will result in i==6,but consider next initializations
int j(int());
T * p2 = new T();
}
我发现 的值为j
1,但这应该是 0,因为int()
它是一个值等于 0 的临时值。
此外,运算符的语法new
是new typename
,但这里T()
将是一个临时对象而不是类型名称。
int j(int());
这没有声明一个对象。相反,它声明了一个函数,该函数将函数作为参数,并返回int
. 它作为参数的函数类型是这样的:
typedef int (*funtype)();
也就是说,一个函数返回int
,并且不接受任何参数。
这种声明的解析通常称为:
并且在new
语法中,T()
不会创建临时对象。这不是它应该被看到的方式。相反,您必须查看new T()
首先为 type 对象分配内存的整个表达式T
,然后在该内存中构造该对象。如果T
是用户定义类型,则在分配内存后调用默认构造函数来构造对象。
new 运算符的语法也是 typename *variable_name = new typename,但这里
T()
将是一个临时对象,而不是类型名称。
与 Most Vexing Parse 类似,T()
根据上下文有不同的含义。它并不总是产生临时的,但一般会初始化一些新的匿名对象或子对象。对象可能是
T()
在表达式中,T()
如果在构造函数中出现在主体之前,则基子对象,或者T()
如果出现在 之后,则指针的所指对象new
。请注意,指针有名称,但对象是匿名的。new T
并new T()
做一些稍微不同的事情:对于某些类型,保留new T
未初始化的值。(官方术语是default-initialization。)基本子对象或临时对象没有相应的语法结构:基本子对象通过省略初始化器进行默认初始化,而临时对象不允许默认初始化。区别很小,因为在所有这些情况下,如果您定义了一个构造函数,就会调用一个构造函数,并且应该始终定义一个构造函数,并且它应该始终初始化所有成员。例外是基本类型int
和简单结构,如std::array<char, 1000>
.
为了安全起见,最好避免new T
只是new T()
为了确保在没有构造函数的情况下将事物很好地归零。