为什么C ++ 11不支持在构造函数初始化列表中的初始化? [英] Why doesn't C++11 curly brace initialzation in constructor initialization list work when parens initializaton does?

查看:334
本文介绍了为什么C ++ 11不支持在构造函数初始化列表中的初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

初始化抽象类型的引用时,构造函数初始化列表中的{}初始化是如何不同于初始化的?下面的类Bar:

How is {} initialization in a constructor initialization list different from () initialization when initializing reference to abstract types? Take class Bar below:

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};

}

编译时出现错误

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;

更改行

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

通过阅读Stroustrup的C ++ 11书,我的印象是{}在大多数情况下与()相同,除非在使用std :: initializer_list<>和其他构造函数的构造函数之间存在模糊性,以及使用auto作为类型的情况,我都不在这里。

Reading through Stroustrup's C++11 book, I was under the impression that {} was the same as () in most all cases, except where there was an ambiguity between constructors that take std::initializer_list<> and other constructors, and cases where using auto as the type, neither of which I'm doing here.

推荐答案

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

Short answer: This was a bug in the Standard which is fixed in C++14, and g++ 4.9 has the fix (retroactively applied to C++11 mode too). Defect Report 1288

这里有一个更简单的例子:

Here's a simpler example:

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

在C ++ 11的文本中, S const& y {x}; 不要将 y 绑定到 x ;其实意思是创建一个临时并绑定一个引用。从C ++ 11 [dcl.init.ref] / 3:

In the text of C++11, the meaning of S const &y {x}; is not to bind y to x; in fact the meaning is to create a temporary and bind a reference to that. From C++11 [dcl.init.ref]/3:


否则,如果T是引用类型,由T引用的类型的prvalue临时是列表初始化的,并且引用绑定到该临时。 [注意:像往常一样,如果引用类型是非const类型的左值引用,则绑定将失败,程序不成形。 -end note]

Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is list-initialized, and the reference is bound to that temporary. [Note: As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. —end note ]

这很傻,显然这个代码的意图是绑定 y 直接到 x 。在C ++ 14中,文本已更改:

This is pretty silly , clearly the intent of this code is to bind y directly to x. In C++14 the text was changed:


否则,如果初始化器列表有一个E类型的元素,引用类型或其引用类型与E引用相关,对象或引用从该元素初始化;

Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element;

是与自身(或其基类之一)相关的引用,在我的样例中和你的实际代码中,它应该实际绑定正确。

Since a type is reference-related to itself (or one of its base classes), in my sample here and in your actual code, it should actually bind correctly.

您的错误消息来自编译器遵循C ++ 11字样,并试图从 base 创建一个临时表,以将引用绑定到;并且此操作失败,因为 base 是抽象类型。

Your error message comes from the compiler following the C++11 wording and attempting to create a temporary from base to bind the reference to; and this fails because base is of an abstract type.

这篇关于为什么C ++ 11不支持在构造函数初始化列表中的初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆