5

以下のソースコードをコンパイルしようとすると、次のエラーが発生しました。このエラーが存在する理由と、それを修正する方法を誰かが説明できますか?

エラー1エラーC2758:'A :: s_':コンストラクタベース/メンバー初期化子で初期化する必要があります

#include <iostream>
#include <string>

using namespace std;

class A
{
public:
    A(string& s) : s_(s) { cout << "A::ctor" << endl; }
    A(const A& rhs)      { cout << "A::copy" << endl; }
    ~A()                 { cout << "A::dtor" << endl; }

    A& operator=(const A& rhs) { cout << "A::copyassign" << endl; }

private:
    string& s_;    
};

int main()
{

    return 0;
}
4

3 に答える 3

10

まず第一に、あなたA::s_std::string;への参照です。つまり、どこかに存在しなければならない何かを参照しているということです。

彼の参照型と、参照が作成された時点で初期化する必要があるという事実のためにA::s_、すべてのAコンストラクターで初期化する必要があります(他のユーザーが指摘しているように)。

class A
{
public:
    A(string& s) : s_(s)
    { cout << "A::ctor" << endl; }

    A(const A& rhs) : s_(rhs.s_) // <-- here too!!
    { cout << "A::copy" << endl; }

    ~A()
    { cout << "A::dtor" << endl; }

    A& operator=(const A& rhs)
    { cout << "A::copyassign" << endl; }

private:
    string& s_;    
};

そして今、私が最初に述べたことに戻ります。存在するものを参照するA::s_必要があるため、いくつかのことに注意する必要があります。次のコードを参照してください。

int main()
{
    // New A instance:
    A a("hello world");

    return 0;
}

このAインスタンスを構築するためにconst char[12]値を提供します。この値を使用して一時的なstd::stringものが作成され、A::A(string& s)コンストラクターに渡されます。A::s_コンストラクターが終了した後の参照はどこにありますか?一時的にstd::string作成されたものはどうなりますか?寿命が延びるのか、コンストラクターが終了すると死ぬのか。A参照が必要なものであると確信していますか?

std::string s("hello world");

int main()
{
    // New A instance:
    A a(s);

    return 0;
}

上記のコードを使用するAと、同じコンストラクターを呼び出して新しいインスタンスが作成されますがA::A(string& s)、提供された文字列がグローバルスコープにあるため、破棄されずA::s_、インスタンスからはa有効な文字列をその存続期間中参照しますが、実際の脅威はコピーコンストラクターにあります:

std::string s("hello world");

int main()
{
    A a(s);    // a.s_ references the global s.
    A b(a);    // b.s_ references the a.s_ that references the global s.

    return 0;
}

コピーされたオブジェクトの値は、指定されたオブジェクトのを参照しstd::stringます。それはあなたが望むものですか?

于 2012-10-15T07:56:55.000 に答える
2

コピーコンストラクターが参照を初期化することはありません。それが行われることを確認してください:

A(const A &rhs) : s_(rhs.s_) {cout << "A::copy" << endl;}
于 2012-10-15T06:39:41.287 に答える
0
 string& s_;

これは参照変数です。これはオブジェクトの一部であるため、オブジェクトが配置されるときに値を持つ必要があります。これが、コンストラクターの初期化リストを使用してこの属性を初期化する必要がある理由です。

オブジェクトの一部のようにこの属性を使用する必要がない場合は、参照の代わりにポインターを使用できます。

 string* s_;
于 2012-10-15T06:42:05.720 に答える