5

私はこのコードをテストしていますが、なぜこれがコンパイル時に失敗しなかったのか疑問に思っています?. 私は c++11 と g++ 4.7.2 を使用しています。

私の実動コードにも同様の構造があり、実行時にエラーが発生していましたが、間違った引数の型でクラスを構築していることがわかりました。

#include <iostream>
#include <vector>


typedef std::vector<std::string> Word;

class Data {
    public:
        const Word &word;
        Data(Word w) : word(w) {}
};

class Base{
    const Data &data;
    public:
        Base(const Data &d): data(d) {}
        ~Base() {}
};

class Work : public Base{
    public:
        Work(const Data &d): Base(d){}
        ~Work() {}
};


int main(int argc, char **argv){
    Word words;
    words.push_back("work");

    /*
    * I'm confused with this constructor, why this passed the compilation
    * ??
    * Any special rule to reason this scenario ??
    *
    * But obviously it will fail at run time.
    */
    const Work *work  = new Work(words);

    return 0;
}
4

3 に答える 3

10

Dataから構築可能であるため、コンストラクターにWorda を渡すことができます。内部では、渡されたものから のインスタンスが作成され、コンストラクタに渡されます。WordWorkDataWord

次のように、明示的なDataものを取るコンストラクタをマークすることで、これを回避できます。Word

class Data {
    public:
        const Word &word;
        explicit Data(Word w) : word(w) {}
};

そうすれば、コンストラクターを暗黙的に適用できなくなり、Workコンストラクターを明示的に呼び出さない限り、コンストラクターへの呼び出しはコンパイルに失敗しますData

const Work *work  = new Work(words);        // Implicit call, fails to compile.
const Work *work  = new Work(Data(words));  // Explicit call, compiles.
于 2013-09-06T07:51:36.920 に答える
5

参照を取る暗黙の変換コンストラクターがあるため、コンパイル*が機能します。DataWord

Data(Word w) : word(w) {}

これは、次のようなことができることを意味します

Word words;
Data d1 = words;
Data d2(words);

そして、 via コンストラクターWorkから aを構築できます。DataWork(const Data &d): Base(d){}

Work w(d2);

これは、ユーザー定義の変換が 1 つしか含まれないため、以下も有効であることを意味します。

Work w2(words); // constructs Data temporary from words, then constructs w2 with it

この動作は、変換コンストラクターを次のように宣言することで抑制できますexplicit

explicit Data(Word w) : word(w) {}

Data*一時オブジェクトへのダングリング参照が含まれているため、実際には機能しません

于 2013-09-06T07:51:46.470 に答える
2

次のコンストラクターの終了後word、参照型のデータ メンバーは、存在しないオブジェクトを参照します。

class Data {
    public:
        const Word &word;
        Data(Word w) : word(w) {}
};

保持する自動保存期間の変数が作成されますw。その変数への参照を member として保存するwordと、コンストラクターの終了時に参照が破棄されます。

他の問題に関係なく、これはあなたの意図ではないと思います。

于 2013-09-06T08:06:05.533 に答える