大括号进行结构初始化/赋值 [英] struct initialization / assignment with braces

查看:252
本文介绍了大括号进行结构初始化/赋值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义的结构如下:

struct float3 {
float x; 
float y;
float z;

float3 () : x(0), y(0), z(0) {}
float3 (float a, float b, float c) : x(a), y(b), z(c) {}
};

但是在理解初始化/为其成员分配值的不同方式时遇到麻烦.例如:

//Initialization
float3 3Dvec = {1.0, 1.0, 1.0};
float3 3Dvec2 {1.0, 1.0, 1.0};
float3 3Dvec3 (1.0, 1.0, 1.0);

//Assignment
3Dvec = {2.0, 2.0, 2.0};
3Dvec = float3 (2.0, 2.0, 2.0);

所有这些选项都可以与-std = c ++ 11一起使用.但是,在使用-std = c ++ 0x大括号的旧版编译器上,初始化/赋值不起作用.矫正大括号是一种不好的做法吗?哪个选项更习惯?

解决方案

在C ++ 11中,所有这些都是合法的.如果您知道将使用兼容C ++ 11的编译器(至少就列表初始化而言),我想说最好使用大括号语法.这是面向未来且毫不含糊的.

以下是对各个陈述的详细分析:

float3 vec3D = {1.0, 1.0, 1.0};

复制列表初始化.严格按照本书,这会通过调用其3参数构造函数来创建临时float3,然后使用move构造函数(或复制构造函数,如果没有可用的move ctor)初始化vec3D,最后销毁该临时. /p>

在实践中,任何不中断的编译器都将省略临时创建和移动/复制操作,因此不会造成效率低下的情况. 但是,请注意,它要求移动/复制构造函数可访问.例如,您不能初始化这样的不可移动,不可复制的类.

float3 vec3D2 {1.0, 1.0, 1.0};
float3 vec3D3 (1.0, 1.0, 1.0);

这两个都通过调用其3参数构造函数直接初始化vec3D2.我想说括号是最佳语法,因为它是明确的.在这种特殊情况下,这并不重要,但是有时使用括号可能会导致(大多数)令人讨厌的解析 1 .

vec3D = {2.0, 2.0, 2.0};
vec3D = float3 (2.0, 2.0, 2.0);

只要vec3D的类型为float3,它们都是100%相同的.两者都使用其3参数构造函数创建了一个临时float3对象,将该对象传递给vec3D的移动(或复制)赋值运算符,然后销毁了该临时对象.

我想说一个大括号更好,因为这是未来的证明.如果您稍后重命名该类,则大括号将继续按原样工作,而圆括号将需要一个名称更改.同样,如果更改vec3D的类型,则大括号仍将创建vec3D类型的对象,而第二个将继续从float3对象创建和分配.不可能一概而论,但我想通常首选前一种行为.


1 例如:

float3 x(float3());  // a function
//vs.
float3 y{float3{}};  // a variable

I have defined a struct as follows:

struct float3 {
float x; 
float y;
float z;

float3 () : x(0), y(0), z(0) {}
float3 (float a, float b, float c) : x(a), y(b), z(c) {}
};

But i have trouble when it comes to understanding the different ways of initializing / assigning values to its members. For instance:

//Initialization
float3 3Dvec = {1.0, 1.0, 1.0};
float3 3Dvec2 {1.0, 1.0, 1.0};
float3 3Dvec3 (1.0, 1.0, 1.0);

//Assignment
3Dvec = {2.0, 2.0, 2.0};
3Dvec = float3 (2.0, 2.0, 2.0);

All of these options do work with -std=c++11. However on an older compiler with -std=c++0x braces initialization / assignment does not work. Is usign braces a bad practice? Which option is better to get used to?

解决方案

In C++11, all of these are legal. If you know you'll be working with a C++11-compliant compiler (at least as far as list initialisation is concerned), I'd say it's preferable to use the brace syntax. It's future-proof and unambiguous.

Here's a detailed analysis of the individual statements:

float3 vec3D = {1.0, 1.0, 1.0};

Copy-list-initialisation. Strictly by the book, this creates a temporary float3 by calling its 3-parameter constructor, then initialises vec3D by using the move constructor (or copy constructor, if no move ctor is available), and finally destroys the temporary.

In practice, the temporary creation and move/copy operation will be elided by any non-broken compiler, so there is no inefficiency. However, note that it requires the move/copy constructor to be accessible. You cannot initialise a non-movable, non-copyable class like this, for example.

float3 vec3D2 {1.0, 1.0, 1.0};
float3 vec3D3 (1.0, 1.0, 1.0);

Both of these directly initialise vec3D2 by calling its 3-parameter constructor. I'd say the brace one is the optimal syntax, because it's unambiguous. In this particular case, it does not matter, but sometimes, using parentheses can lead to a (most) vexing parse1.

vec3D = {2.0, 2.0, 2.0};
vec3D = float3 (2.0, 2.0, 2.0);

These are 100% identical, as long as the type of vec3D is float3. Both create a temporary float3 object using its 3-parameter constructor, pass that object to the move (or copy) assignment operator of vec3D, and then destroy the temporary.

I'd say the brace one is better, because it's future proof. If you later rename the class, the brace one will continue to work as is, while the parenthesis one will require a name chaage. Also, if you change the type of vec3D, the brace one will still create an object of vec3D's type, while the second one will keep creating and assigning from a float3 object. It's not possible to say universally, but I'd say the former behaviour is usually preferred.


1 An example of that would be:

float3 x(float3());  // a function
//vs.
float3 y{float3{}};  // a variable

这篇关于大括号进行结构初始化/赋值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆