2

まず第一に、これは私よりも言語標準の深さに精通している人々からの承認を得るための健全性チェックの質問です。

次のタイプがあるとしましょう(ただし、非コンストラクターおよび非割り当てメンバー関数は省略しました)。

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は、aはプレーン以外のものであってはなりませんstd::uint16_t。しかし、私は標準からの保証に興味を持っています。これが、PODのC++98/03定義による私の理論的根拠です。

  • half非パブリックフィールド、基本クラス、およびユーザー定義のコンストラクターがあるため、PODタイプにすることはできません。

およびC++11の失われた/拡張された定義:

  • 暗黙的に生成されたコピー/移動コンストラクター/割り当てのみであるため、簡単にコピー可能である必要がありますが、それらfloatとテンプレートのバージョンがまったくカウントされない場合に限ります。これは完全にはわかりません。

  • また、基本タイプのプライベートフィールドが1つと、空の非仮想基本クラスが1つしかないため、標準レイアウトにする必要があります(どの標準でもPODである必要がありますか?)

  • half() = defaultPOD分類を妨げる唯一のことは、それが自明にデフォルトで構築可能ではないということです。これは、C++11の構文を使用することでIMHOが克服できる可能性があります。

私の非常に単純な質問は、私の理論的根拠は完全に正しいのか、それとも、特にユーザー定義のコンストラクターと割り当てが自明なコピー可能としての分類を何らかの形で妨げているという観点から、定義で見落としたり誤解したりしたことはありますか?

注:これをPODと標準レイアウトタイプ(私は完全に理解できます)に関するいくつかの可能な重複に委任したいという衝動を感じたとしても、これは単なる健全性チェックであるため、私の実際の質問に答える簡単なコメントはまだいいでしょう、これはあなたにとって単純または不必要に起こるかもしれませんが、私はただ安全な側にいたいと思います。

4

1 に答える 1

6

はい、half標準レイアウト(9/7)です:基本クラスは空であり、派生クラスはすべての非静的データに対して同じアクセス制御を持ち、仮想および非標準レイアウトのベースまたはメンバーはなく、ベース最初の非静的データメンバーとは異なるタイプです。

定義するコンストラクターと代入演算子は、コンストラクターと代入をコピー(または移動)しないため、クラスが簡単にコピー可能かどうかには関係ありません。

デフォルトのコンストラクターは、ユーザー提供(12.1 / 5)であるため自明ではなく、クラスは自明ではありません。

データメンバーと空のベースには簡単なコピー/移動(12.8 / 12)があるため、コピー/移動はすべて簡単です。デストラクタについても同じであるため、クラスは簡単にコピーできます。

したがって、分析は正しいと思います。引数なしのコンストラクターを削除すると、C ++ 11にPODクラスがあります(C ++ 98にはありません)。

Lucが言うように、PODクラスにデータメンバーが1つしかない場合でも、PODクラスにパディングが含まれないという保証はありません。

C ++ 03では、空の基本クラスの最適化が許可されていますが、必須ではありません。そのため、品質は劣りますが、C++03の実装に準拠することで確実に得られる可能性がありますsizeof(half) == sizeof(half_expr<half>) + sizeof(uint16_t)。が保証されておりsizeof(half_expr<half>) > 0、それが小さければ、uint16_tパディングも合理的に期待できます。

C ++ 11では、レイアウト互換性に関するルールでは、空の基本クラスの最適化を適用する必要があります。一方が基本クラスを持ち、もう一方が基本クラスを持たない2つの標準レイアウトタイプは、レイアウト互換です(9.2 / 17 )、およびレイアウト互換タイプは、ユニオン(9.2 / 19)を介して読み取ることができます。つまり、同じレイアウトである必要があります。パディングは引き続き許可されますが、無意味です。

標準はさておき、実装は、PODクラスがどのように見えるかを示すC++ABIから機能している場合と機能していない場合があります。もしそうなら、ABIはまだC ++ 11に対して最新ではないかもしれませんが、実装によって、すべての標準レイアウトクラスが、PODクラスが定義されているように見えるかどうかに関係なく、確実に見えるようになると思います。また、些細なことです(そして、それはEBC最適化を行います)。これが標準レイアウトのポイントの一種です。「C構造体のようにレイアウトされたクラス」です。

実装では、すべてのクラスタイプを4整列にする必要があると任意に決定することも許可されていると思います。この場合も、パディングが行われます。ただし、これを期待するのは合理的ではないと思います。それを実行するために私が考えることができる唯一の動機は、4整列ポインターが。よりも小さい可能性がある奇妙なアーキテクチャーを使用していることですchar*

于 2012-08-12T16:06:34.237 に答える