在 c++ 中初始化对象的不同方法
Different ways of initializing an object in c++
想象一下这个类:
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;
上面的语句是默认初始化,它导致调用类Entity
的默认构造函数。
Entity ent2();
如果可能的话,编译器会将上述声明视为函数原型。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();
ent4
是ent2
C++11之前的情况的正确版本。默认构造函数作为值初始化的一部分调用。它的形式允许避免歧义解决原则,使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 个元素的向量。但是这个
std::vector<int> v{10};
声明一个向量,该向量由值为 10 的 int 类型的单个元素初始化。发生这种情况是因为std::vector
有一个定义了以下签名的构造函数:
vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
如果您不能在不触发 MVP 的情况下使用 (),也不能在不调用不需要的构造函数的情况下使用 {},则值初始化赋值语法允许解决此问题。
附录:必看CppCon 2018:尼古拉·乔苏蒂斯"C++初始化的噩梦">
- 使用std::函数映射对象方法
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 从父类方法返回子类对象
- 在他自己的方法中,有可能将一个对象取消引用到另一个对象吗
- 为什么此派生对象无法访问基类的后递减方法?
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 正在调用shared_ptr对象方法
- 将方法转换为调用该方法的成员函子对象会导致崩溃
- 检查哪个对象调用了另一个对象的对象方法
- CPU 瓶颈;处理具有许多非静态对象的 3D 场景渲染的简单方法
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 没有取消引用/解包对象的标准方法?
- 使用 gmock c++ 在真实对象上调用方法
- 当我调用对象的方法时,对象的成员会发生变化
- 根据对象类调用不同的方法
- 如何在C++中循环访问未知对象方法?
- 使用动态实例化的对象填充矢量的快速方法
- 对类中的对象使用方法