中初始化对象的不同方式

中初始化对象的不同方式

本文介绍了c++中初始化对象的不同方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下这个类:

class Entity {
public:
    int x, y;

    Entity() : x(0), y(0) { }
    Entity(int x, int y) : x(x), y(y) { }
}

这里有多种使用我认为我知道的初始化类的方法:

And here are multiple ways of initializing the class with what I think I know:

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

我知道可以在堆内存上创建一个对象,但这不是我目前想要的.

I know that's it's possible to make an object on the heap memory, but that's not what I am looking for at this moment.

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

My question is, what's the difference between these ways of initializing an object?

我不确定我应该在什么时候使用哪个.

I'm not sure which one I should use when.

推荐答案

Entity ent1;

上面的语句使用类Entity的默认构造函数.

The statement above uses default constructor of class Entity.

Entity ent2();

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

The declaration above will be treated by compiler as a function prototype if that's possible. It's known as a case of most vexing parse (MVP) and its existence led to appearance of misleading "clever dumb rule": "never use parenthesis".

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

In statement like this a user-defined constructor is invoked for ent3:

Entity ent3(1, 2);

MVP 可以罢工的另一种情况是这样的:

Another case where MVP can strike is something like this:

Entity ent3_1(int(a), int(b));  // It's not what it looks like.

上面的

ent3_1 不是变量.该语句声明了一个带有两个 int 参数的函数.int(a)int a 相同是 C 语言和声明语法的遗产.

ent3_1 above is not a variable. The statement declares a function with two int parameters. int(a) being same as int a is legacy of C language and declaration syntax there.

Entity ent4 = Entity();

ent4 是 C++11 之前 ent2 案例的正确 版本.默认构造函数作为值初始化的一部分被调用.它的形式允许避免使ent2ent3_1不正确的歧义解决原则.这里的等号不是赋值,因为这里不会发生 operator= 调用.它是用于标记初始化表达式的声明语法的一部分.

ent4 is a proper version of ent2 case until C++11. Default constructor is invoked as part of value initialization. Its form allows to avoid an ambiguity solving principle which makes ent2 and ent3_1 incorrect. Equal sign here is not an assignment, for no operator= call will happen here. It's part of declaration syntax meant to markup the initialization expression.

Entity ent5 = Entity(2, 3);

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

ent5 is a version of ent3 case. User-defined constructor invoked as part of value initialization.

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

Your question is tagged as C++11, and C++11 allows uniform initialization syntax:

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!

请注意,统一初始化语法有一个警告.例如.这一行

Note that uniform initialization syntax has a caveat. E.g. this line

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

声明一个包含 10 个元素的向量.但是这个

declares a vector of 10 elements. But this one

std::vector<int> v{10};

声明一个向量,该向量使用值为 10 的 int 类型的单个元素进行初始化.发生这种情况是因为 std::vector 有一个定义了以下签名的构造函数:

declares a vector initialized with single element of type int with value 10. This happens because std::vector has a constructor with following signature defined:

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

如果您既不能在不触发 MVP 的情况下使用 () 也不能在不调用不需要的构造函数的情况下使用 {} 时,值初始化赋值语法可以解决该问题.

In case that you can't use neither () without triggering MVP nor {} without invoking undesired constructor, the value initialization assignment syntax allows to resolve the issue.

附录:必须观看 CppCon 2018:Nicolai JosuttisC++ 初始化的噩梦""

这篇关于c++中初始化对象的不同方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 02:38