2

C ++ 11、§9/ 7:

標準レイアウトクラスは、次のようなクラスです。

  • タイプnon-standard-layoutクラス(またはそのようなタイプの配列)または参照の非静的データメンバーはありません。
  • 仮想関数も仮想基本クラスもありません。
  • すべての非静的データメンバーに対して同じアクセス制御があり、
  • 非標準レイアウトの基本クラスはありません。
  • 最も派生したクラスに非静的データメンバーがなく、非静的データメンバーを持つ基本クラスが多くても1つないか、非静的データメンバーを持つ基本クラスがない。
  • 最初の非静的データメンバーと同じタイプの基本クラスはありません。

では、標準レイアウトのクラスをコピーできないようにする方法はありますか?はいの場合、どのように?

boost :: noncopyableからプライベートに継承すると、コピーコンストラクターがプライベートになります(したがって、標準のレイアウトではないため)。boost :: noncopyableの実装は次のようになります:

  class noncopyable
  {
   protected:
      noncopyable() {}
      ~noncopyable() {}
   private:  // emphasize the following members are private
      noncopyable( const noncopyable& );
      const noncopyable& operator=( const noncopyable& );
  };

プライベートセクションのため、標準のレイアウトクラスではありません。また、プライベート継承が標準のレイアウトルールに違反するかどうかも確認します。


#include <boost/noncopyable.hpp>
#include <iostream>
const int N = 50;
struct A
{
    int data[N];
};
struct B : private boost::noncopyable
{
    int data[N];
};
struct C
{
    A data[10];
};
struct D : private boost::noncopyable
{
    B data[10];
};

int main() {
    std::cout<<sizeof(A)<<std::endl;
    std::cout<<sizeof(B)<<std::endl;

    std::cout<<sizeof(C)<<std::endl;
    std::cout<<sizeof(D)<<std::endl;
}

出力は次のとおりです。

200
200
2000
2004

上記の例は、からプライベートに継承boost::noncopyableすると、クラスが標準レイアウトに準拠しないように変更されることを示しています。これがg++のバグ(私はg ++ 4.6.1を使用しています)なのか、それとも標準に違反しているのかわかりません。

4

2 に答える 2

4

ここに混乱があると思います:

  • 標準のレイアウト プロパティは、属性 (および属性のみ) の影響を受けます。
  • copyable プロパティはメソッドの影響を受けます (メソッドの存在、不在、アクセシビリティ)

2 つの概念は直交しています。

アップデート:

以下は、以下とまったく同じ動作を示しboost::noncopyableます。

#include <iostream>

struct foo {};

struct B : foo { int data; };

struct D : foo { B data; };

int main() {
  D d;
  std::cout << (char*)(&d.data) - (char*)(&d) << "\n";
}

結果は4です。

これは次の理由によるものだと思います。

  • 最初の非静的データ メンバーと同じ型の基底クラスはありません。

実際、実験ではint a;D前にa を導入しdataてもそのサイズは増加しないことが示されています。Bから継承するということは、 (最初の非静的データメンバー) が(の基底クラス) と同じ型であると見なされることをfoo意味すると思います。datafooD

これはあいまいさにつながります。コンパイラがこのパディングを導入しなかった場合foo* f = &dと同じアドレスになります。foo* g = &b.data;

于 2012-01-31T10:43:46.280 に答える
0

クラスをコピー不可にするには、次の 2 つのことを行う必要があります。

  1. コピー コンストラクターを非公開にします。
  2. 代入演算子を非公開にします。(クラス自体と同じ種類の別の型が割り当てられる場所)。

その動作を取得するためだけに、一部のブースト クラスから継承する必要はありません。

そして、いくつかの派手な「標準レイアウト」のアイデアを気にかけている人を追加できますか. 必要なものをプログラムして、この極端な宇宙理論に屈しないでください。

于 2012-01-31T10:38:16.497 に答える