Dog *a=new Dog() 和 Dog *a=new Dog{} 区别
在C++中,new Dog()
和new Dog{}
这两种形式都用于动态分配Dog
类的对象,但它们在对象初始化上有细微的差别。这些差别源自于C++11引入的统一初始化语法(uniform initialization),也称为列表初始化(list initialization)。
示例
考虑一个带有不同成员变量的类:
#include <iostream>class Dog {
public:Dog() : age(5) {} // 默认构造函数int age;
};class Cat {
public:int age;
};int main() {Dog* dog1 = new Dog();Dog* dog2 = new Dog{};Cat* cat1 = new Cat();Cat* cat2 = new Cat{};std::cout << "dog1->age: " << dog1->age << std::endl; // dog1->age: 5std::cout << "dog2->age: " << dog2->age << std::endl; // dog2->age: 5std::cout << "cat1->age: " << cat1->age << std::endl; // cat1->age: (未定义行为)std::cout << "cat2->age: " << cat2->age << std::endl; // cat2->age: 0delete dog1;delete dog2;delete cat1;delete cat2;return 0;
}
在这个例子中:
dog1
和dog2
都通过默认构造函数初始化,age
的值为5。cat1
通过new Cat()
未初始化其成员变量,cat1->age
的值是未定义的。cat2
通过new Cat{}
列表初始化,其成员变量被值初始化为0。
总结
new Dog()
和new Dog{}
在大多数情况下效果相同,特别是当类有默认构造函数时。new Dog{}
使用列表初始化,提供更强的初始化保障,确保成员变量被正确初始化,防止未定义行为。- 使用列表初始化(
new Dog{}
)可以增强代码的安全性和可读性,尤其是在处理未初始化变量时。
Dog *a=new Dog() 和 Dog *a=new Dog 区别
在C++中,Dog *a = new Dog();
和 Dog *a = new Dog;
在语义上有微妙的区别,尤其是在涉及到构造函数的情况下。以下是它们之间的区别:
Dog *a = new Dog();
这行代码创建了一个Dog
类的对象,并将其地址赋给指向Dog
类的指针a
。这里使用的是圆括号的构造形式,即调用了Dog
类的构造函数。
Dog *a = new Dog;
这行代码也创建了一个Dog
类的对象,并将其地址赋给指向Dog
类的指针a
。但这里使用的是不带圆括号的构造形式。
在这两种情况下,都会调用Dog
类的构造函数,但是在以下情况下可能会有差异:
- 默认构造函数:如果
Dog
类有默认构造函数,两种形式的行为将相同,都会调用默认构造函数。 - 禁止隐式转换:如果
Dog
类禁止了隐式转换构造函数,那么只有Dog()
形式的语句是合法的,而Dog
形式的语句会导致编译错误。
示例
#include <iostream>class Dog {
public:explicit Dog() { std::cout << "Dog default constructor" << std::endl; }
};int main() {Dog *a = new Dog(); // 调用 Dog() 构造函数// Dog *b = new Dog; // 这行代码会导致编译错误,因为构造函数是显式的delete a;return 0;
}