c ++构造函数的奇怪行为

Har*_*s N 5 c++ c++11

我正在测试这段代码并想知道为什么在编译时没有失败?我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)

Fré*_*idi 10

Data是可构造的Word,所以你可以传递WordWork构造函数.在引擎盖下,Data将从传递的实例创建一个实例Word,然后传递给构造函数.

您可以通过标记构造的避免这种情况Data,需要一个Word作为明确的,就像这样:

class Data {
    public:
        const Word &word;
        explicit Data(Word w) : word(w) {}
};
Run Code Online (Sandbox Code Playgroud)

这样,构造函数不能再被隐式应用,并且Work除非显式调用Data构造函数,否则对构造函数的调用将无法编译:

const Work *work  = new Work(words);        // Implicit call, fails to compile.
const Work *work  = new Work(Data(words));  // Explicit call, compiles.
Run Code Online (Sandbox Code Playgroud)


jua*_*nza 5

工作编译*因为Data有一个带Word引用的隐式转换构造函数:

Data(Word w) : word(w) {}
Run Code Online (Sandbox Code Playgroud)

这意味着你可以做一些事情

Word words;
Data d1 = words;
Data d2(words);
Run Code Online (Sandbox Code Playgroud)

你可以WorkDatavia构造函数构造一个Work(const Data &d): Base(d){}:

Work w(d2);
Run Code Online (Sandbox Code Playgroud)

这意味着以下内容也有效,因为它只涉及一个用户定义的转换:

Work w2(words); // constructs Data temporary from words, then constructs w2 with it
Run Code Online (Sandbox Code Playgroud)

通过将转换构造函数声明为explicit:可以抑制此行为:

explicit Data(Word w) : word(w) {}
Run Code Online (Sandbox Code Playgroud)

*您实际上并不工作,因为它涉及对临时Data对象的悬空引用