0

次の2つのクラスの違いを知りたいです。

例 1:

class A
{
string name;
public:
  A(const char* _name):name(_name){}
  void print(){cout<<"A's name:"<<name<<endl;}
};

例 2:

class A
{
string name;
public:
  A(const char* _name){name(_name);}
  void print(){cout<<"A's name:"<<name<<endl;}}

例 1 が渡され、最後の例が間違っているのはなぜですか? ありがとう

4

6 に答える 6

3

最初の例は、実際の初期化です。これには、メンバーを設定する唯一の方法であることconstや、適切な例外安全性があることなど、多くの利点があります。

2 番目の例は有効な C++ ではありません。代わりに を書いた場合name = name_、これは通常の割り当てになります。もちろん、これが常に可能であるとは限りません。オブジェクトが であるconstか、代入演算子が定義されていない可能性があります。このアプローチは、オブジェクトがデフォルトで初期化され、割り当てられているため、最初の例よりも効率が低下する可能性があります。

イニシャライザリストがコンストラクタ本体の前にある理由について。まあ、それは言語が定義された方法です。

于 2011-05-02T11:16:42.673 に答える
3

例 1 では、文字列を指定された値ですぐに初期化します。例 2 では、最初に空の文字列を作成し、後で割り当てます。

いくつかのパフォーマンスの違いと、コピー コンストラクターの処理などによる違いの可能性を無視しても、基本的に同じ結果になります。

ただし、constメンバーを使用したら、例 1 の方法を使用する必要があります。たとえば、通常は次の方法で一意の ID を作成します。

class SomeObject
{
    static unsigned int nextID = 0;
    const unsigned int ID;
    SomeObject() : ID(nextID++)
    {
        // you can't change ID here anymore due to it being const
    }
}
于 2011-05-02T11:22:26.960 に答える
2

それが言語の定義方法です。メンバー初期化子は、コンストラクターの本体の前に配置する必要があります。

于 2011-05-02T11:15:51.873 に答える
1

最初の例では、メンバー名は char * をパラメーターとして取得する ctr で初期化されます。

2 番目のケースでは、最初にデフォルトの ctr で初期化され、後で代入演算子 (operator=) によって値を取得します。そのため、すでにそこに構築されているというケースが間違っているため、 ctr をもう一度使用することはできず、代入演算子を使用することができます。

于 2011-05-02T11:17:14.260 に答える
0

初期化リストの背後にある動機は、(参照/ポインターフィールドではなく)値によってオブジェクトを保持するconstフィールドによるものです。

このようなフィールドは、(その恒常性のために)1回だけ初期化する必要があります。C ++に初期化リストがない場合、ctorは次のようになります。

class A {
public:
  const string s;
  const string t;

  A() {
    // Access to either s or t is not allowed - they weren't initialized
    s = "some-string";
    // now you can access s but you can't access t
    f(*this);

    t = "some other string";
    // From now you can access both ...
  }
}


void f(A& a) {
  // Can you access a.s or a.t?
  cout << a.s << a.t;
}

初期化リストがないと、ctorは部分的に初期化された型のオブジェクトをA関数に渡すことができ、その関数はどのフィールドがまだ初期化されているかを知る方法がありません。コンパイラ/リンカがチェックするにはリスクが高すぎて非常に困難です。

于 2011-05-02T11:28:10.137 に答える
0

その理由は、初期化子リストと関数本体で名前検索の動作が異なるためです。

class A
{
  std::string foo; // member name
public:
  A(const char* foo) // argument name
    : foo(foo) // member foo, followed by argument foo.
  {
    std::cout << foo; // argument foo.
  }
};

初期化子リストが関数本体内にある場合、 memberfooと argumentの間にあいまいさが生じますfoo

于 2011-05-02T11:18:51.347 に答える