17

それは単に好みですか、それとも特定のインスタンスが必要な場合がありますか? 初期化のために次のバリアントを参照しています

T t(e); // direct initialization
T t = e; // copy initialization
4

2 に答える 2

20

あなたが説明するものの実際の名前は、暗黙的および明示的な代入ではありませんが、次のとおりです。

  • コピー初期化:T x = a;
  • 直接初期化:T x(a);

それらは同等ではありません。特に、変換が必要なコンテキストでは、たとえばTがクラス型でaあり、別の型である場合です (変換を含まないコンテキストの例については、Alf コメントを参照してください)。次のコードを検討してください。

class Test
{
public:
    explicit Test(int i) { /* ... */ }
};

int main()
{
    Test t(0);  // OK : calls Test::Test(int)
    Test u = 0; // KO : constructor is marked explicit
}

標準 (8.5/14) を言い換えると:

  • ソースの型が宛先のクラスと同じ、またはその派生クラスである直接初期化およびコピー初期化の場合、コンストラクターが考慮されます。
  • main私の例の 2 行目のように、他のコピー初期化のケースでは、ユーザー定義の変換シーケンスが考慮されます。Test暗黙的な変換のためのコンストラクターの使用がexplicitキーワードによって許可されていないため、2 行目はコンパイルに失敗します。
于 2010-11-27T20:42:08.977 に答える
11

のような直接初期化

std::istringstream  stream( "blah blah" );

問題の型(ここstd::istringstreamではC ++標準ライブラリから)にアクセス可能なコピーコンストラクタがない場合に必要です。

のようなコピーの初期化

std::istringstream  stream = "blah blah";   //! NOT VALID

の右側に一時オブジェクトが作成されたかのように実行され、=宣言されている変数を初期化するためにその一時オブジェクトが使用されるかのように実行されるため、アクセス可能なコピーコンストラクタが必要です。

逆に、C ++ 98では、中括弧の初期化子を使用するためにコピー初期化構文が必要です。たとえば、直接初期化を使用して集計を初期化することはできません。ただし、中括弧の初期化子でコピーの初期化を使用できます。

#include <string>
using namespace std;

struct Answer
{
    int     nVotes;
    string  description;
};    

int main()
{
    Answer const  incorrect   = { 26, "they're the same!" };
    Answer const  correct     = { -1, "nah, they're different, actually" };
}

したがって、大きな違いがあります。

私は一般的に、明快さのためにコピー初期化構文を好みます。ただし、上記のように、残念ながら直接初期化が必要な場合があります。C++の教科書の著者であるFrancisGlassborowなどの一部の人々は、代わりに、優先する初期化構文として直接初期化を採用しています(理由はわかりませんが、私の目にはあまり明確ではなく、「最も厄介な解析」の問題が発生します)。場合によってはコピーの初期化が必要ですが、それは残念なことです。

乾杯&hth。、

于 2010-11-28T04:43:40.613 に答える