17

編集:明確にするために、構造体には関数がないため、構造体は何もしません。イニシャライザーリストを使用し、コンストラクターの本体を空のままにしておくことが当面の問題だと思った印象を与えたと思います。

2つの値を保持するために構造体を使用していて、次のような任意の構造体を作成できるようにコンストラクターがあるとします。

struct twoValues
{
    int x;
    int y;

    twoValues(int x_, int y_):y(y_),x(x_)
    {}
};

someFunction(twoValues(1,2));

これにより、これを行う必要がなくなります。

twoValues anInstance;
anInstance.x=1;
anInstance.y=2;
someFunction(anInstance);

編集:あなたはすべて正しいです、私は次のように初期化することもできます:

twoValues anInstance = {1,2};

これには何の問題もありませんが、C ++テストからいくつかのフィードバックがあり、否定的なフィードバックマークの1つは、「何もしない構造体のコンストラクター」でした。私は私をテストしている人との接触が限られていたので、理由を尋ねることはありませんでした。

それは悪いことですか、そしてなぜですか?私はむしろそれを続けたいと思います。

4

8 に答える 8

17

構造体が何に使用されているかによって異なります。他の人が言っているように、コンストラクターは、クラスがもはやPODではなく、集約初期化を使用できないことを意味します。特に、名前空間スコープに次のようなものを含めることはできません。

TwoValues const table[] =
{
    { 1, 2 },
    { 3, 4 },
    // ...
};

あなたが持つことができます:

TwoValues const table[] =
{
    TwoValues(  1, 2  ),
    TwoValues(  3, 4  ),
    // ...
};

ただし、これはより冗長であり、動的な初期化を意味するため、初期化の問題が発生する可能性があります。

一方、コンストラクターがないと、一時的なインスタンスをその場で作成することはできません。それ以外の:

extern void f( TwoValues const& );
//  ...

f( TwoValues( 1, 2 ) );

あなたは書く必要があります:

extern void f( TwoValues const& );
//  ...

TwoValues tmp = { 1, 2 };
f( tmp );

オブジェクトが動的に割り当てられる場合は、さらに悪いことになります。最初に割り当ててから初期化するか、上記のように一時的なものを作成してからnew TwoValues( tmp )、暗黙のコピーコンストラクターを作成して使用する必要があるためです。

あなたが選択する必要があります。構造体の用途に応じて、どちらかが優先されます。一方では、静的テーブルで排他的に使用される構造体がたくさんあり、意図的にコンストラクターを持たず(静的初期化をサポートする型のみを含む)、コードの構成に多く使用します。一方、Nodeツリーやグラフの線に沿って、クラスの内部にある構造体もたくさんあります。これらには、その場での作成を容易にするために、ほとんどの場合コンストラクターがあります。アプリケーションでの構造体の役割を知らなければ、「正しい」答えはありません。

于 2012-07-18T09:01:11.473 に答える
13

空のコンストラクターを宣言すると、副作用があります。

コンストラクターの本体が空であっても、コンストラクターと見なされるため、オブジェクトがPODであるなど、特定のオブジェクトプロパティが失われます。

場合によっては、プレーンオールドデータ型を使用する必要があります。これにより、特定の理由なしに実行したことを実行することが望ましくなくなる可能性があります。

次のセクションで、デフォルトコンストラクタを使用しない初期化について詳しく説明します。


&&

「何もしないコンストラクター」を明示的に定義せずに、メンバーを値で初期化できます。以下のスニペットのように、中括弧の初期化構文を使用するだけです。

struct Obj {
  int x, y;
};

Obj a = {1,3}; /* a.x = 1, a.y = 2 */

コンストラクターがないことの欠点は、C ++ 03 = { ... }を作成するときに、特定の状況で使用してオブジェクトを初期化できないことです。

C ++ 11でこれが修正されます。関連する例については、次のセクションを参照してください。


C ++ 11では、中括弧( = { ... })を使用した初期化の機能が強化されています。

以下のスニペットに見られるObjように、この投稿の前半と同じ形式の初期化を使用していても、の定義済みコンストラクターが呼び出されます。

struct DoubleBoth {
  DoubleBoth (int x, int y)
    : x(x*2), y(y*2) 
  {}  

  int x, y;
};

以下のスニペットは、C++11より前はすべて違法でした

DoubleBoth a = {1,2}; /* a.x = 2, a.y = 4 */

struct Wrapper {
  Wrapper ()
    : value {3,4}
  {}

  DoubleBoth value;
};

void func (DoubleBoth v = {1,2}) {  // c++11 only
  ...
}

func ({4,5}); // c++11 only, c++03 requires `DoubleBoth obj (0,1); func (obj);`
于 2012-07-18T08:40:55.317 に答える
7

リストで初期化するよりも、この種のコンストラクターを使用する方がはるかに安全です。

リストで初期化する場合:

twoValues anInstance = {1, 2};

それは実際には構造体のメンバーの順序に依存します。ほとんどの場合、これは最初から完全にランダムです。

別のプログラマーがたまたま別のメンバーを追加したり、メンバーをアルファベットで並べ替えたりすると、正しく機能しません。

NAMEによって適切なメンバーに値を割り当てるコンストラクターを使用する方がはるかに安全です。

于 2012-07-18T08:47:45.703 に答える
7

あなたはtwoValuesPODになるのをやめ、構造体のインスタンスがデフォルトまたは値で初期化されるのを防ぎました。これは多くの場合望ましいプロパティです。個人的には、単純なC ++ 03フレンドリーなアプローチが必要な場合は、一時インスタンスを作成するための無料の関数が必要です。

例えば

twoValues makeTwoValues(int x_, int y_)
{
    twoValues tmp = { x_, y_ };
    return tmp;
}

void f() {
    someFunction(makeTwoValues(1,2));
}

たとえば、タイプのメンバーを初期化するtwoValues

class X {
    twoValues tv;
public:
    X(int x, int y) : tv(makeTwoValues(x, y)) {}
};
于 2012-07-18T08:44:06.167 に答える
4

おそらく、次のように初期化できるためです。

twoValues anInstance = {1, 2};

ただし、コンストラクターがないとanInstance、C++03の別の構造体の初期化子リストでを初期化することはできません。例えば:

struct Bar {
  twoValues v_;
  Bar() : v_(1,2) {} // error!
  Bar() { v_ = {1,2}; } // have to assign value in constructor body
  Bar() : v_{1,2} {} // OK in C++11
};

したがって、実際にはコンストラクターは何かを実行し、C++03では非常に便利な目的を果たします。C++11ではそれほど問題にはなりません。

于 2012-07-18T08:40:46.960 に答える
2

この建設業者には何の問題もありません。

また、それは何かをします、それは私がそのようなコンストラクターに期待するものであるxとyへの値に影響を与えます。

しかし、おそらくあなたの会社には、別の方法でそれを行うべきだというコーディング規則がいくつかあります。その場合は、フィードバックをいただいた人に聞いて、必要な修正を加えることをお勧めします。

于 2012-07-18T08:42:02.220 に答える
2

コンストラクターは、構造体を非PODにしますが、これは場合によっては望ましくない場合があります。

構造体にコンストラクターがない場合、構造体はPOD 1になり、次のように初期化できます。

twoValues anInstance = {1,2}; //C++03 and C++11 both!
twoValues anInstance {1,2};   //C++11 only

良いです。

1.実際には、構造体を非PODにする他のことがあります。したがって、構造体にコンストラクターがないからといって、必ずしもPODであるとは限りません。あなたはそれらの他のものが何であるかを知るためにこの投稿を見たいと思います。

于 2012-07-18T08:42:27.810 に答える
0

構造体はコンストラクターを持つことができ、構文はC++のクラスの場合と同じです。クラスと構造体の違いは、クラスメンバーはデフォルトでプライベートであり、構造体メンバーはデフォルトでパブリックであるということです。ただし、ユニオンは構造体でコンストラクターを許可しません。ただし、ユニオンでコンストラクターを作成することはできます。

于 2012-07-18T08:43:23.050 に答える