2014-06-10 252 views
4

我已經定義了一個結構如下:結構初始化/分配

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的大型編譯器中,花括號初始化/賦值不起作用。使用大括號是不好的做法嗎?哪個選項更適合習慣?

+0

你應該寫代碼,以任一C++ 11或C++ 03標準,而不是一些中途點(其你的舊編譯器似乎是)。你在這裏展示的是一個很好的C++ 11實踐。 – juanchopanza

+0

@juanchopanza我不同意這裏;爲什麼不充分利用它所支持的C++ 11功能來提供可用的編譯器。例如,我們正在使用gcc 4.8和VS 2010;我們是否應該因爲VS2010不支持'constexpr'而辭去lambdas,智能指針,'auto'和移動語義? – Angew

+1

@Angew如果你完全控制你的中途點編譯器,那很好。否則,它的可移植性太差了。這正是我想要了解的。 – juanchopanza

回答

2

在C++ 11中,所有這些都是合法的。如果你知道你將使用C++ 11兼容的編譯器(至少就列表初始化而言),我會說最好使用大括號語法。這是未來和明確的。

這裏的個別報表的詳細分析:

float3 vec3D = {1.0, 1.0, 1.0}; 

複製一覽初始化。嚴格來說,通過調用其3參數構造函數創建一個臨時float3,然後通過使用移動構造函數(或複製構造函數,如果沒有移動窗口可用)初始化vec3D,並最終銷燬臨時文件。

實際上,臨時創建和移動/複製操作將被任何非破壞的編譯器所忽略,所以沒有低效率。 但是,請注意,它需要移動/複製構造函數可訪問。例如,你不能初始化一個不可移動的,不可複製的類。

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

這兩種通過調用其3參數的構造直接初始化vec3D2。我會說支架一是最佳的語法,因爲它是明確的。在這種特殊情況下,這並不重要,但有時使用括號可能會導致產生一個(most) vexing parse

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

這些是100%相同,只要vec3D類型是float3。兩者都使用其3參數構造函數創建臨時float3對象,將該對象傳遞給移動(或複製)賦值運算符vec3D,然後銷燬該臨時對象。

我想說一個更好,因爲它是未來的證明。如果稍後重命名該類,則括號將繼續按原樣工作,而括號中則需要名稱chaage。另外,如果更改vec3D的類型,大括號仍將創建vec3D類型的對象,而第二個將繼續從float3對象創建和分配。這是不可能說普遍,但我會說前者的行爲通常是首選。


這方面的一個例子是:

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