如果我没有定义自己的构造函数,那么Base *b = new Base;
与Base *b = new Base();
之间是否存在差异?
答案 0 :(得分:8)
初始化是标准中遵循的PITA ......然而,两个已经存在的答案在他们错过的内容中是不正确的,这使得他们确认没有差异。
在没有用户定义构造函数的类中调用new T
和new T()
之间存在巨大差异。在第一种情况下,对象将是 default-initialized ,而在第二种情况下,它将是`value-initialized *。如果对象包含任何POD子对象,则第一个将保留未初始化的POD子对象,而第二个将子对象设置为0。
struct test {
int x;
std::string s;
};
int main() {
std::auto_ptr<test> a( new test );
assert( a->s.empty() ); // ok, s is string, has default constructor
// default constructor sets it to empty
// assert( a->x == 0 ); // this cannot be asserted, the value of a->x is
// undefined
std::auto_ptr<test> b( new test() );
assert( b->s.empty() ); // again, the string constructor sets to empty
assert( b->x == 0 ); // this is guaranteed by *value-initialization*
}
对于漫长的道路...用户定义的类的 default-initialize 意味着调用默认构造函数。在没有用户提供的默认构造函数的情况下,它将调用隐式定义的默认构造函数,这相当于具有空初始化列表和空体(test::test() {}
)的构造函数,这反过来将导致每个非POD子对象的默认初始化,并使所有POD子对象保持未初始化状态。由于std::string
有一个用户(通过包含标准库编写器的某个用户定义)提供的构造函数,它将调用这样的构造函数,但它不会对{{{{{ 1}}成员。
也就是说,对于用用户提供的默认构造函数,x
和new T
是相同的。对于没有这种构造函数的类,它取决于类的内容。
答案 1 :(得分:3)
编辑:看到@David的答案 - 这是错的,但我不能删除它因为它被接受
两种情况都没有区别 - 如果你定义自己的构造函数也没关系。
唯一的区别是对于原始类型(即int
或float
),添加()
会将值初始化为零。 (Demonstration on Codepad)
请参阅此示例(输出位于codepad)
#include <iostream>
struct ConstructorChecker
{
ConstructorChecker()
{
std::cout << "Hey look! A new constructor checker!" << std::endl;
}
};
struct BasicClass
{
};
int main()
{
//Note constructor called in both cases.
ConstructorChecker *one = new ConstructorChecker;
delete one;
ConstructorChecker *two = new ConstructorChecker();
delete two;
//Same deal -- just because the compiler provides the constructor doesn't mean
//it behaves any differently.
BasicClass *basic = new BasicClass;
delete basic;
BasicClass *basic2 = new BasicClass();
delete basic2;
return 0;
}
答案 2 :(得分:-1)
正如比利所说,两者都是同一个。
这称为'值初始化语法'($ 8.5 / 7)。
初始化程序为的对象 空的圆括号,即(), 应进行价值初始化。