2011-09-24 68 views
4

C++ 11標準保證字節對每個字節的副本始終對POD類型有效。但是,某些微不足道的類型呢?C++ 11中字節對字節的類型拷貝?

下面是一個例子:

struct trivial 
{ 
    int x; 
    int y; 
    trivial(int i) : x(2 * i) { std::cout << "Constructed." << std::endl; } 
}; 

如果我要複製這個結構,字節對字節,是保證正確複製,即使它在技術上不是POD?什麼時候畫的線是而不是好的字節複製對象?

+1

相關:http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/7189821#7189821 –

回答

9

是的,它是保證複製正確。

引述FDIS,§3.9/ 2:

對於平凡複製的類型T的任何對象(比基類的其他子對象)時,對象是否保持類型的有效值T,組成對象的基礎字節可以被複制到charunsigned char的數組中。如果將charunsigned char的數組內容複製回對象中,則該對象將隨後保持其原始值。

和§3.9/ 3:

對於任何平凡複製的類型T,如果兩個指針T指向不同T對象obj1obj2,其中既不obj1也不obj2是一個鹼基如果構成obj1的基礎字節被複制到obj2中,則obj2將隨後保持與obj1相同的值。

所以你問的要求是,§3.9/ 9:

運算類型,枚舉類型,指針類型,指針成員類型,std::nullptr_t,而這些CV-合格版本類型統稱爲標量類型。標量類型,POD類,這類類型的數組和cv-qualified這些類型的版本統稱爲POD類型標量類型,可簡單複製的類類型,此類類型的數組以及這些類型的cv限定版本統稱爲可微複製類型

而且§9/ 6:

平凡能夠複製類是一個類:

  • 沒有非平凡的拷貝構造函數,
  • 沒有非瑣碎的移動構造函數,
  • 沒有非平凡的複製賦值運算符,
  • 沒有不平凡的移動賦值操作符,並且
  • 有一個微不足道的析構函數。
+4

trivial :: trivial(int)'不是默認或複製構造函數。因此,它並不真正影響「微不足道」的複製瑣事。 – MSN

+1

MSN說的很重要,因爲回到C++ 03,構造函數會影響POD性。所以C++ 11允許這樣做,而C++ 03則沒有。 –

3

如果標準規定它只是爲POD類型定義的(我還沒有仔細檢查過C++ 11標準,所以我不知道你的爭用是否正確(a))和你做一個非POD類型,它沒有定義的行爲。期。

在一些實現中,在行星對齊時的某些環境中,它可能在一天中的某些時間工作。它可能工作絕大多數時候。如果你重視可移植性,那麼這仍然不是一個好主意。


(一)更多的調查後,它將顯示你的具體情況是好的。該標準的第3.9/3(n3242 draft,但我會感到驚訝,如果它已經從這麼晚草案太大的改變)指出:

對於任何平凡複製的類型T,如果兩個指針至T點不同ŧ對象obj1和obj2其中,obj1和obj2都不是基類子對象,如果組成obj1的基礎字節被複制到obj2中,則obj2將隨後保持與obj1相同的值。

第九節定義(在高電平)什麼是「平凡能夠複製」是指:

甲平凡能夠複製類是一類:
- 不具有非平凡複製構造(12.8) ,
- 沒有非平凡的舉動構造函數(12.8),
- 沒有非平凡的拷貝賦值運算符(13.5.3,12.8),
- 沒有非平凡的舉動賦值運算符(13.5.3, 12.8)和
- 有一個微不足道的析構函數(12.4)。

與引用的部分進入更詳細地在每個區域中,12.8用於複製和分配用於移動類對象和13.5.3

+0

-1他的類型是「平凡的可複製的「,這是C++ 11中用於從其值表示重建對象的唯一要求。 – ildjarn

+0

@ildjarn:因此在開始的「如果」。 – paxdiablo

+0

所以你的答案是「如果你說的話是真的那麼它是非法的,但我不知道你說的話是否屬實」?這個答案如何? – ildjarn

4

C++ 11打破了POD類型的定義成更有用的類別,具體「瑣碎」和「標準佈局」。你的例子是標準佈局,並且可以複製,儘管構造函數可以防止它變得微不足道。平凡能夠複製類型保證是安全地逐字節複製:

對於任何對象平凡 能夠複製類型T的(比基類子對象等),對象是否保持 類型的有效值T,構成對象的基礎字節(1.7)可以被複制到一個char或unsigned char的數組中.40如果char或unsigned char的數組的內容被複制回到對象中,則對象應該隨後 保持其原始價值。

因此,不需要POD狀態以這種方式安全複製,但可以識別非POD類型的子集。