初始化的区别不仅在于其形式,还在于
正在初始化的实体类型。在本例中,它是一个类类型对象,具有已定义的默认构造函数以及带参数的构造函数。
Entity ent1;
上面的语句是默认初始化,这会导致调用该类的默认构造函数Entity
.
Entity ent2();
如果可能的话,上面的声明将被编译器视为函数原型。Entity
将返回函数的类型ent2
,不带任何参数。这被称为一个案例最麻烦的解析(MVP)及其存在导致了误导性的“聪明的愚蠢规则”的出现:“永远不要使用括号”。
在这样的语句中,将调用与参数列表匹配的用户定义的构造函数ent3
object:
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();
ent4
is a proper的版本ent2
C++11 之前的情况。默认构造函数作为值初始化的一部分被调用。它的形式可以避免歧义解决原则,这使得ent2
and 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 个元素的向量。但这个
std::vector<int> v{10};
声明一个用值为 10 的 int 类型的单个元素初始化的向量。发生这种情况是因为std::vector
有一个定义了以下签名的构造函数:
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
如果您既不能使用 () 而不触发 MVP,也不能使用 {} 而不调用不需要的构造函数,则可以使用值初始化赋值语法来解决该问题。
附录:必看