2013-01-16 23 views
5

可能重複:
Classes store data members in sequential memory?類變量 - 對齊

只想問,爲什麼下面是正確的:

template<class T> 
class Vec3 { 
public: 
    // values 
    T x,y,z; 

    // returns i-th komponent (i=0,1,2) (RHS array operator) 
    const T operator[] (unsigned int i) const { 
    return *(&x+i); 
    } 
} 

或者換句話說:爲什麼始終保證x,y和z在內存中總是以sizeof(T)爲單位。在兩個變量之間不能存在破碎洞,從而讓這個運算符返回一個錯誤的值?

+0

如果你需要索引,爲什麼不把它'模板類的Vector3 {市民:性病::陣列 XS; };'? – Fanael

回答

6

保證xyz總是sizeof(T)單元隔開在存儲器中。可以在兩者之間添加填充字節。
它作爲實現細節被忽略。
唯一保證的是,在類/結構的開始和POD結構/類的第一個成員之間不會有填充。

不保證代碼中operator[]的實現將始終有效。

參考:
C++ 11:9.2類成員[class.mem]

14)非靜態數據(非聯合類)具有相同的訪問控制部件(第11條)被分配如此 以後成員在一個類對象中有更高的地址。未指定具有不同訪問控制的成員的非靜態數據 的分配順序(11)。 執行對齊要求可能會導致兩個相鄰成員不會立即被分配;因此可能需要 來管理虛擬功能(10.3)和虛擬基類(10.1)。

+0

你的意思是「它作爲實現細節被遺漏」。 –

+0

即使是關於第一個成員的地址的保證只適用於POD結構。(或者對於C++ 11中的佈局兼容結構。) –

+0

@AdamMagaluk:這意味着編譯器可以自由地在類/結構成員之間添加所需的填充字節數。該標準在這方面沒有強制任何具體要求。 –

0

爲了避免碎片孔你可以控制的排列是這樣的:

#ifdef compiling_with_msvc 
#pragma pack(1) 
#endif 
template<class T> 
class Vec3 { 
public: 
    // values 
    T x,y,z; 

    // returns i-th komponent (i=0,1,2) (RHS array operator) 
    const T operator[] (unsigned int i) const { 
     return *(&x+i); 
    } 
#ifdef compiling_with_gcc 
}__attribute__((packed)); 
#else 
}; 
#endif 

如果你可以使用一個C++11 compiler可以控制在standard way對齊。

但是,如果你不關心的類的內存中表示,考慮到使用union

template <typename T> 
union Vec3 
{ 
    T x, y, z; 
    struct 
    { 
     T value[3]; 
    } vector; 
}; 

與工會,你不必爲了關心對齊存取權限與[]每個組件:

Vec3<unsigned int> v3; 

v3.vector.value[0] = 1; 
v3.vector.value[1] = 2; 
v3.vector.value[2] = 3; 
+0

它實際上指定的地方,在你的聯合解決方案中,這些字段將被對齊(例如x和值[0],y和值[1])?它使*感*,但這是實際指定/保證任何地方? – rmhartog

+0

是的,'x'和'value [0]','y'和'value [1]'...將具有相同的地址...但我不能保證''''''''''值[0]'<->'值[1]'你會發現填充字節;它將取決於'union'的數據類型,數據對齊和對齊控制 –