C++ 在c++;

C++ 在c++;,c++,class,c++11,constructor,initialization,C++,Class,C++11,Constructor,Initialization,想象一下这个班级: 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();

想象一下这个班级:

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
我知道在堆内存中创建对象是可能的,但这不是我现在要寻找的

我的问题是,这些初始化对象的方法有什么区别

我不确定什么时候该用哪个

Entity ent1;
上面的语句使用类
实体
的默认构造函数


如果可能的话,编译器将把上面的声明视为函数原型。它被称为最令人烦恼的解析(MVP)案例,它的存在导致了误导性的“聪明愚蠢规则”的出现:“永远不要使用括号”


在这样的语句中,为
ent3
调用用户定义的构造函数:

Entity ent3(1, 2);
MVP可以罢工的另一种情况如下:

Entity ent3_1(int(a), int(b));  // It's not what it looks like.
上面的
ent3_1
不是一个变量。该语句声明了一个具有两个int参数的函数


在C++11之前,
ent4
ent2
正确版本。默认构造函数作为值初始化的一部分被调用。其形式允许避免使
ent2
ent3\u 1
不正确的歧义解决原则。此处的等号不是赋值,因为此处不会发生
运算符=
调用。它是声明语法的一部分,用于标记初始化表达式


ent5
是ent3案例的一个版本。作为值初始化的一部分调用的用户定义构造函数


您的问题标记为C++11,C++11允许统一的初始化语法:

Entity ent12{};     // This is a legal alternative of ent2 case
Entity ent13{1, 2};
Entity ent13{ int(a), int(b) }; // Not a function anymore
Entity ent14 = {};
Entity ent15 = Entity{2, 3};
请注意,统一初始化语法有一个警告。例如,这条线

std::vector<int> v(10); 

如果在不触发MVP的情况下不能使用()或在不调用不需要的构造函数的情况下不能使用{},则值初始化赋值语法允许解决该问题。

Entity ent2()
是一个函数声明。不,这意味着根本不存在
实体
ent2
是一个函数。不,这意味着您正在声明一个名为
ent2
的函数,该函数返回一个
实体
。您可以在C++11及更高版本中使用{}。查找统一初始化。您提供的示例是C++87(MVP可能允许可变ent2,编译器不一致)@JesperJuhl,这不是我的“个人”昵称。这本书是根据Stroustroup的第一期书改编的。从本质上讲,他在1986-1987年第一次描述的语言是C++87。因为没有其他描述,请您进一步解释
()
{}
之间的区别,以及如何让程序以不同的方式解释它们?我自己的类是否有可能有一个构造函数,当用
{}
调用时它会做一些事情,当用
()
调用时它会做一些其他事情?@CătălinaSîrbu()或{}之间的区别是提供参数与统一初始化。上面给出了如何导致不同行为的示例,但这是一个完全不同的问题。对于任意形式的大括号内容,您无法做到这一点。定义接受
std::initializer\u list
的构造函数是上述技巧的关键,因为初始化列表的T类型元素默认情况下将绑定到该代理类。滥用此选项可能会导致混乱。回答很好,但我忽略了一个要点,
=…
表单要求存在副本构造函数并具有可访问性,即使忽略了该副本构造函数调用。@cmaster是否真的这样做了?关键是,至少在旧标准中,拷贝是否可以省略并不重要,拷贝构造函数必须存在并且可以访问,因为拷贝是语义的一部分。也就是说,编译器检查复制构造函数是否存在并可访问,并且只有当该测试为阳性时,它才会继续删除对复制构造函数的调用。我认为他们已经改变了/计划在最新的标准中改变这一点,但直到C++11,我已经验证了这一点。
Entity ent5 = Entity(2, 3);
Entity ent12{};     // This is a legal alternative of ent2 case
Entity ent13{1, 2};
Entity ent13{ int(a), int(b) }; // Not a function anymore
Entity ent14 = {};
Entity ent15 = Entity{2, 3};
std::vector<int> v(10); 
std::vector<int> v{10};
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );