2012-08-12 32 views
2

首先,這是一個理智的檢查問題,以便得到某些人更好的認可 - 深入瞭解語言標準的深度。使用用戶自定義構造函數的普通和POD類型

比方說,我有以下幾種類型(雖然我離開了任何非構造函數和非分配成員函數):

template<typename E> struct half_expr 
{ 
}; 

class half : public half_expr<half> 
{ 
public: 
    half(); 
    explicit half(float); 
    template<typename E> half(const half_expr<E>&); 

    half& operator=(float); 
    template<typename E> half& operator=(const half_expr<E>&); 

private: 
    half(std::uint16_t, bool); 

    std::uint16_t data_; 
}; 

好了,任何合理的實施half不應該在別的內存比普通的std::uint16_t。但是我對標準的保證感興趣。這是我的理由根據POD的C++ 98/03 defition:

  • half不能是POD類型,因爲它是具有非公共字段,基類和用戶定義的構造。

和C++ 11 losened /擴展定義:

  • 它應該是平凡可複製的,因爲它只有隱式生成複製/移動的構造/分配,但是隻有隻要這些float和模板版本不以任何方式計算,我不完全確定。

  • 還應該標準的佈局,因爲它只有基本類型和單個空非虛擬基類的單個私有字段(這應該是POD在任何標準,是嗎?)

  • 的唯一阻礙POD分類的事情是它不是普通的默認可構造的,這可能通過使用C++ 11的half() = default語法來克服。

我很簡單的問題就是:是我的理念完全正確,或是否有我忽視或在定義曲解,尤其是在用戶定義的構造和分配光的任何東西莫名其妙地阻礙分類爲平凡可複製?

注:即使你覺得敦促委託本約POD和標準佈局類型(我可以prefectly理解),簡單的評論回答我的實際問題仍然是不錯的一些可能重複的,因爲這僅僅是一種完整的檢查,可能會對您造成簡單或過度的影響,但我只想保持安全。

+0

這種類型可以在您正確分析時輕鬆複製(但不是微不足道的)和標準佈局,但對於其大小的保證而言,這並不意味着太多。 – 2012-08-12 16:06:12

+1

您的假設可以通過['std :: is_trivially_copyable'](http://en.cppreference.com/w/cpp/types/is_trivially_copyable)和['std :: is_standard_layout'](http:// en.cppreference.com/w/cpp/types/is_standard_layout),當然['std :: is_pod'](http://en.cppreference.com/w/cpp/types/is_pod)。 – 2012-08-12 16:26:55

+2

@JoachimPileborg假設所使用的實現在這方面完全符合標準。 – 2012-08-12 16:31:31

回答

6

是的,half是標準佈局(9/7):基類是空的,派生類對所有非靜態數據具有相同的訪問控制,沒有虛擬的,沒有非標準佈局的基礎或成員,並且基數與第一個非靜態數據成員是不同的類型。

您定義的構造函數和賦值運算符是而不是複製(或移動)構造函數和賦值,因此它們與該類是否可以複製是無關的。

默認的構造函數並不重要,因爲它是用戶提供的(12.1/5),所以類不是微不足道的。

副本/移動都是微不足道的,因爲數據成員和空白基數有微不足道的複製/移動(12.8/12)。析構函數也一樣,所以這個類是可複製的。

所以我相信你的分析是正確的 - 刪除無參數的構造函數,並且在C++ 11中有一個POD類(但不在C++ 98中)。

正如Luc所說,標準中沒有保證POD類不包含填充,即使它只有一個數據成員。

在C++ 03中,空基類優化是允許,不是必需的,所以質量很差但符合C++ 03的實現肯定會給你sizeof(half) == sizeof(half_expr<half>) + sizeof(uint16_t)。它保證sizeof(half_expr<half>) > 0,如果它小於uint16_t你可以合理地期待填充。

在C++ 11中,有效的佈局兼容性規則要求應用空基類優化 - 兩個標準佈局類型(其中一個具有基類而另一個不具有基類佈局兼容) (9.2/17),並且佈局兼容類型可以通過聯合(9.2/19)讀取,這意味着它們必須具有相同的佈局。填充仍然是允許的,但毫無意義。

除了標準之外,您的實現可能會或可能不會從C++ ABI工作,它告訴您POD類是什麼樣的。如果是這樣的話,我預計儘管ABI可能並不是最新的C++ 11,但實際上,實現將使所有標準佈局類看起來像定義POD類的外觀,無論它們是也是微不足道的(它會做EBC優化)。這就是標準佈局的要點:「像C結構一樣佈置的類」。

我認爲,實現也允許任意決定所有類類型必須是4對齊的,在這種情況下,你會得到填充。不過,我認爲期待這一點並不合理,因爲我能想到的唯一動機就是你在一些奇怪的架構中,4對齊的指針可能小於char*

+3

「此外,允許使用空的基類優化,而不是必需的」不,它是* C++ 11中的標準佈局規則所要求的。如果一個類型是標準佈局,那麼C++ 11有效地要求空的基類或派生類在佈局中不佔用空間。兩種類型可以與完全不同的基類安排兼容。非標準佈局類不需要空基優化。 – 2012-08-12 22:45:08

+0

@NicolBolas說[真相](http://stackoverflow.com/a/10789707/981959) – 2012-08-13 20:42:23

相關問題