我在某處讀取了一段用於定義三維座標的代碼。於是,他們用x
,y
& z
協調這樣如下:使用聯合的結構和相同大小的數組有什麼優勢
union
{
struct
{
float x, y, z;
};
float _v[3];
};
我的問題是,爲什麼union
這裏需要也是爲什麼要使用結構與陣列的優勢在哪裏?
我在某處讀取了一段用於定義三維座標的代碼。於是,他們用x
,y
& z
協調這樣如下:使用聯合的結構和相同大小的數組有什麼優勢
union
{
struct
{
float x, y, z;
};
float _v[3];
};
我的問題是,爲什麼union
這裏需要也是爲什麼要使用結構與陣列的優勢在哪裏?
重要注意事項:此構造會導致未定義的行爲。接下來是對作者意圖的描述,不幸的是,許多編譯器正是將作者期望的行爲翻譯成了,這反過來又導致了類似的代碼氾濫。
union
構造不是真的需要在這裏:作者使用它的方便。他們之所以把union
沒有給自己一個語法來訪問x
,y
,並且z
兩種不同的方式:
coord.x
,coord.y
,或coord.z
,或coord._v[0]
,coord._v[1]
或coord._v[2]
。,提供類似的功能,而不會在不確定的行爲的一種方法是使用內聯成員函數爲您的訪問:
struct Vector3D {
int v[3];
int& x() { return v[0]; }
int& y() { return v[1]; }
int& z() { return v[2]; }
};
int main() {
Vector3D coord;
coord.v[0] = 5;
cout << coord.x() << endl;
coord.y() = 10;
cout << coord.v[1] << endl;
return 0;
}
這種方式可以解決三維座標爲結構..
foo.x;
foo.y; // etc
但它也可以讓你獲得3個變量作爲數組,而佔據相同的空間(這是該計劃至少)訪問它們像..
foo._v[0] // x, etc
無論如何,這就是主意。但是,當結構在成員之間有任何填充的時候,你的數組將會錯位,並且你最終會讀取垃圾值。長話短說,這段代碼有未定義的行爲,一個不應該使用的不好的實現。
正如吉爾·貝茨說,這樣你可以(也許)訪問的3個座標都爲x, y, z
和v[0], v[1], v[2]
但根據@Richard Critten的評論,這實際上是一個UB。
你可以像這樣得到同樣的結果在一個「安全」的方式:
struct Coordinates
{
Coordinates():x(v[0]), y(v[1]), z(v[2])
{
}
int v[3];
int& x;
int& y;
int& z;
};
即使用引用數組值和構造函數初始化它們
這個結構的尺寸會比你在OP表示雙方的結合顯然是不同的(大)
「這個結構的大小將明顯不同(更大)」這是一個相當輕描淡寫的問題:大小將*顯着*更大。實際上,在考慮內存對齊的填充效果之前,您至少要花費兩倍的內存,這非常昂貴。在ideone上,大小從12個字節增長到40個字節([demo](http://ideone.com/oAOwAC))。 – dasblinkenlight
無,除非你想未定義行爲或需要調查和檢查的編譯器擴展。 _「...未定義的行爲可以從最近未編寫的工會成員中讀取。」_參見:http://en.cppreference.com/w/cpp/language/union –
聯合使結構陣列佔據相同的空間。試圖讓'x'成爲'_v [0]'的同義詞是一種破解。它假定結構中沒有填充,並且會在添加它們的系統上突破。 – StoryTeller
這將是一個非常奇怪的編譯器,將不同地填充結構和數組。雖然它在C++語言標準方面是未定義的行爲,但它通常在編譯器將生成的代碼方面理解得很好。雖然語言純粹主義者討厭它,但編寫嵌入代碼的人通常依賴於這種事情。 –