想象一下这个类:
class Entity {
public:
int x, y;
Entity() : x(0), y(0) { }
Entity(int x, int y) : x(x), y(y) { }
}
这里有多种我认为我知道的初始化类的方法:
Entity ent1; //Uses the default constructor, so x=0 and y=0
Entity ent2(); //Uses the default constructor, so x=0 and y=0 (Not sure)
Entity ent3(1, 2); //Made constructor, so x=1 and y=2
Entity ent4 = Entity(); //Default constructor, so x=0 and y=0
Entity ent5 = Entity(2, 3); //Made constructor, so x=2 and y=3
我知道可以在堆内存上创建一个对象,但这不是我现在要找的。p>
我的问题是,这些初始化对象的方式有什么区别?
我不确定什么时候应该使用哪一个。
最佳答案
初始化的区别不仅在于它采用的形式,还在于 在正在初始化的实体类型中。在这种情况下,它是一个类类型的对象,具有已定义的默认构造函数以及带参数的构造函数。
Entity ent1;
上面的语句是默认初始化,它会调用 Entity
类的默认构造函数。
Entity ent2();
如果可能的话,上面的声明将被编译器视为函数原型(prototype)。 Entity
将返回函数 ent2
的类型,它不带任何参数。它被称为最令人烦恼的解析 (MVP) 的案例,它的存在导致出现误导性的“聪明的愚蠢规则”:“永远不要使用括号”。
在这样的语句中,为 ent3
对象调用匹配参数列表的用户定义构造函数:
Entity ent3(1, 2); // calls Entity(int x, int y)
另一种 MVP 可以罢工的情况是这样的:
Entity ent3_1(int(a), int(b)); // It's not what it looks like.
上面的 ent3_1
不是变量。该语句声明了一个带有两个 int 参数的函数。 int(a)
与 int a
相同是 C 语言和声明语法的遗留问题,忽略了“额外”括号。
Entity ent4 = Entity();
在 C++11 之前,ent4
是 ent2
的正确 版本。默认构造函数作为值初始化的一部分被调用。它的形式允许避免使 ent2
和 ent3_1
不正确的歧义解决原则。这里的等号不是赋值,因为这里不会发生 operator=
调用。它是声明语法的一部分,用于标记初始化表达式。
Entity ent5 = Entity(2, 3);
ent5
是 ent3 大小写的一个版本。作为值初始化的一部分调用的用户定义的构造函数。
你的问题被标记为 C++11,C++11 允许统一的初始化语法:
Entity ent12{}; // This is a legal alternative of ent2 case
Entity ent13{1, 2}; // A call to constructor or member initialization
Entity ent13{ int(a), int(b) }; // Not a function anymore
Entity ent14 = {}; // Not an assignment
Entity ent15 = Entity{2, 3}; // Not an assignment either!
请注意,统一初始化语法有一个警告。例如。这条线
std::vector<int> v(10);
声明一个包含 10 个元素的 vector 。但是这个
std::vector<int> v{10};
声明一个用值为 10 的 int 类型的单个元素初始化的 vector 。发生这种情况是因为 std::vector
具有定义了以下签名的构造函数:
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
如果您既不能在不触发 MVP 的情况下使用 (),也不能在不调用不需要的构造函数的情况下使用 {},则值初始化赋值语法可以解决该问题。
附录:必看CppCon 2018: Nicolai Josuttis “The Nightmare of Initialization in C++”
关于c++ - C++中初始化对象的不同方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49802012/