4

重複の可能性:
C++ の構造体とクラスの違いは何ですか?

この質問は多く寄せられ、回答されてきましたが、ときどき混乱するものに遭遇します。

要約すると、C++ 構造体とクラスの違いは、有名な既定のパブリック アクセスとプライベート アクセスです。それとは別に、C++ コンパイラは構造体をクラスと同じように扱います。構造体には、コンストラクター、コピー コンストラクター、仮想関数を含めることができます。など。また、構造体のメモリ レイアウトは、クラスのメモリ レイアウトと同じです。C++ に構造体がある理由は、C との下位互換性のためです。

人々は構造体とクラスのどちらを使用するかについて混乱しているため、単純な古いデータがある場合は、構造体を使用するのが経験則です。それ以外の場合は、クラスを使用してください。そして、構造体はシリアル化に優れていると読みましたが、これがどこから来たのかはわかりません。

それから先日、私はこの記事に出くわしました: http://www.codeproject.com/Articles/468882/Introduction-to-a-Cplusplus-low-level-object-model

(直接引用して)次の場合は次のようになります。

struct SomeStruct
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
};  

次にこれ:

void SomeFunction()
{
    SomeStruct someStructVariable;
    // usage of someStructVariable
    ... 
}  

この:

void SomeFunction()
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4;      
    // usage of 4 variables
    ... 
}

同じだ。

生成されるマシンコードは、構造体がある場合、または関数内の変数を書き留めるだけの場合と同じです。もちろん、これは構造体が POD の場合にのみ適用されます。

これは私が混乱するところです。効果的な C++ で Scott Meyers は、空のクラスなどというものは存在しないと述べています。

私たちが持っている場合:

class EmptyClass { };

実際には、コンパイラによって次のようにレイアウトされます。

class EmptyClass
{
    EmptyClass() {}
    ~EmptyClass() {}
    ...
};

したがって、空のクラスはありません。

上記の構造体をクラスに変更すると、次のようになります。

class SomeClass
{ 
    int  field1;
    char field2 
    double field3;
    bool  field4; 
}; 

それは次のことを意味しますか:

void SomeFunction()
{
    someClass someClassVariable;
    // usage of someClassVariable
    ... 
}  

この:

void SomeFunction()
{ 
    int  field1;
    char field2 
    double field3;
    bool  field4;      
    // usage of 4 variables
    ... 
}

機械語の命令は同じですか?someClass コンストラクターへの呼び出しがないことは? または、割り当てられたメモリは、クラスをインスタンス化するか、変数を個別に定義するのと同じですか? そして、パディングはどうですか?構造体とクラスはパディングを行います。これらの場合、パディングは同じでしょうか?

誰かがこれに光を当てることができれば、本当に感謝しています。

4

4 に答える 4

2

唯一の違いは、構造体のメンバーがデフォルトでパブリックであるのに対し、クラスのメンバーはデフォルトでプライベートであることです (デフォルトで言う場合、「特に指定がない限り」という意味です)。このコードをチェックしてください:

#include <iostream>
using namespace std;

struct A {
 int x;
 int y;
};

class A obj1;

int main() {
  obj1.x = 0;
  obj1.y = 1;
  cout << obj1.x << " " << obj1.y << endl;
  return 0;
}

コードは正常にコンパイルおよび実行されます。

于 2012-10-08T05:43:33.383 に答える
2

その記事の著者は間違っていると思います。2 つの関数の構造体と非メンバー変数のレイアウト バージョンの間におそらく違いはありませんが、これが保証されているとは思いません。ここで保証されていると私が考えることができる唯一のことは、それがPODであるため、構造体のアドレスと最初のメンバーが同じであるということです...そして、各メンバーはその後のある時点でメモリ内に続きます。

どちらの場合も、POD であるため (クラスもそうである可能性があるため、間違いを犯さないでください)、データは初期化されます。

とにかく、そのような仮定をしないことをお勧めします。それを活用するコードを書いたとしても、なぜそうしたいのか想像できませんが、他のほとんどの開発者はとにかく困惑するでしょう。あなたがしなければならない場合にのみ、法的な本を分割してください。それ以外の場合は、人々が慣れ親しんだ方法でコーディングすることを好みます。この中で唯一重要な点は、POD オブジェクトは明示的に初期化しない限り初期化されないということです。

于 2012-10-08T04:11:13.670 に答える
1

There is no difference between structs and classes besides the default for protection (note that default protection type for base classes is different also). Books and my own 20+ years experience tells this.

Regarding default empty ctor/dector. Standard is not asking for this. Nevertheless some compiler may generate this empty pair of ctor/dector. Every reasonable optimizer would immediately throw them away. If at some place a function that is doing nothing is called, how can you detect this? How this can affect anything besides consuming CPU cycles?

MSVC is not generating useless functions. It is reasonable to think that every good compiler will do the same.

Regarding the examples

struct SomeStruct
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
}; 

void SomeFunction()
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4;      
   ... 
}

The padding rules, order in memory, etc may be and most likely will be completely different. Optimizer may easily throw away unused local variable. It is much less likely (if possible at all) that optimizer will remove a data field from the struct. For this to happen the struct should be in defined in cpp file, certain flags should be set, etc.

I am not sure you will find any docs about padding of local vars on the stack. AFAIK, this is 100% up to compiler for making this layout. On the contrary, layout of the structs/classes are described, there are #pargma and command line keys that control this, etc.

于 2012-10-08T04:27:59.373 に答える
1

機械語の命令は同じですか?

そうでない理由はありません。しかし、規格からの保証はありません。

someClass コンストラクターへの呼び出しがないことは?

はい、コンストラクターへの呼び出しがあります。ただし、コンストラクターは機能しません (すべてのメンバーが POD であり、宣言する方法someClass someClassVariable;によって値の初期化が発生し、POD メンバーに対しては何も行われないため)。したがって、行う作業がないため、指示を植える必要はありません。

または、割り当てられたメモリは、クラスをインスタンス化するか、変数を個別に定義するのと同じですか?

クラスには、変数を個別に宣言してもパディングが含まれない場合があります。
また、コンパイラが個々の変数を最適化するのがより簡単になると確信しています。

そして、パディングはどうですか?

はい、構造体 (構造体/クラス) にパディングの可能性があります。

構造体とクラスはパディングを行います。これらの場合、パディングは同じでしょうか?

はい。必ずリンゴとリンゴを比較してください(つまり)

struct SomeStruct
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
}; 
class SomeStruct
{ 
  public:           /// Make sure you add this line. Now they are identical.
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
}; 
于 2012-10-08T06:03:41.737 に答える