当parens初始化时,为什么构造函数初始化列表中的C++ 11大括号初始化不起作用?

ory*_*unn 12 c++ initialization reference c++11 list-initialization

初始化对抽象类型的引用时,构造函数初始化列表中的{}初始化如何与()初始化不同?以下课程栏:

class AbstractBase
{
public:
    AbstractBase() {}
    virtual ~AbstractBase() = default;

    virtual void ab() = 0;
};

class Foo : public AbstractBase
{
public:
    Foo() {}

    void ab() {}
};

class Bar
{
public:
    Bar(const AbstractBase& base) : myBase{base} {}

private:
    const AbstractBase& myBase;
};


int main()
{
    Foo f{};
    Bar b{f};

}
Run Code Online (Sandbox Code Playgroud)

编译时,我收到错误

test5.cpp: In constructor ‘Bar::Bar(const AbstractBase&)’:
test5.cpp:22:48: error: cannot allocate an object of abstract type ‘AbstractBase’
     Bar(const AbstractBase& base) : myBase{base}
                                                ^
test5.cpp:2:7: note:   because the following virtual functions are pure within ‘AbstractBase’:
 class AbstractBase
       ^
test5.cpp:8:18: note:   virtual void AbstractBase::ab()
     virtual void ab() = 0;
Run Code Online (Sandbox Code Playgroud)

换线

Bar(const AbstractBase& base) : myBase(base) {}
Run Code Online (Sandbox Code Playgroud)

它编译并运行良好.

通过阅读Stroustrup的C++ 11书籍,我认为在大多数情况下{}与()相同,除非在构造函数之间存在歧义,这些构造函数采用std :: initializer_list <>和其他构造函数,以及案例在哪里使用auto作为类型,我在这里都没有.

M.M*_*M.M 13

简短回答:这是标准中的一个错误,它在C++ 14中修复,而g ++ 4.9有修复(也追溯应用于C++ 11模式).缺陷报告1288


这是一个更简单的例子:

struct S
{
    int x;
    S() { }     // this causes S to not be an aggregate (otherwise aggregate 
                // initialization is used instead of list initialization)
};

S x = 5;
S const &y { x } ;    

x = 6;
std::cout << y << std::endl;     // output : 5
Run Code Online (Sandbox Code Playgroud)

在C++ 11的文字,的意思S const &y {x};是不结合yx; 实际上意思是创建一个临时的并绑定对它的引用.来自C++ 11 [dcl.init.ref]/3:

否则,如果T是引用类型,则由T 引用的类型的prvalue临时值被列表初始化,并且引用绑定到该临时值.[注意:像往常一样,如果引用类型是非const类型的左值引用,则绑定将失败并且程序格式错误. - 尾注]

这非常愚蠢,显然这段代码的意图是y直接绑定到x.在C++ 14中,文本被更改:

否则,如果初始化列表具有E类型的单个元素且T不是引用类型或其引用类型与E引用相关,则从该元素初始化对象或引用;

由于类型与其自身(或其基类之一)的引用相关,在我的示例和实际代码中,它实际上应该正确绑定.


您的错误消息来自编译器遵循C++ 11的措辞并尝试创建临时base来绑定引用; 这是失败的,因为base它是一个抽象类型.

  • @oryan_dunn试图将临时绑定到非const引用 (3认同)