使用删除的拷贝构造函数初始化const引用成员 [英] Initialization of const reference member with deleted copy constructor

查看:410
本文介绍了使用删除的拷贝构造函数初始化const引用成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个代码,带有 const A&在 B 中的一个成员,其中 A 有一个删除的拷贝构造函数,在GCC 4.8.1中,但它在clang 3.4中工作正常:

This code, with a const A& a member in B, where A has a deleted copy constructor, doesn't compile in GCC 4.8.1, but it works OK in clang 3.4:

class A {
public:
    A() = default;
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

class B{
public:
    B(const A& a)
        : a{a}
    { }
private:
    const A& a;
};

int main()
{
    A a{};
    B b{a};
}

哪一个编译器是正确的?

Which one of the compilers is right?

GCC中的错误是:

prog.cpp: In constructor ‘B::B(const A&)’:
prog.cpp:11:14: error: use of deleted function ‘A::A(const A&)’
        : a{a}
            ^
prog.cpp:4:5: error: declared here
    A(const A&) = delete;
    ^

Ideone: http://ideone.com/x1CVwx

推荐答案

class A {
public:
    A() = default;
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

int main()
{
  A a{};
  A const& ar1(a); 
  A const& ar2{a}; // fails on gcc 4.8
}

ar2 在gcc-4.8上失败,并显示错误

The initialization of ar2 fails on gcc-4.8 with the error

error: use of deleted function ‘A::A(const A&)’

它在clang3.4和gcc4.9上干净地编译。这是向CWG 问题1288 提交的决议的结果。

It compiles cleanly on clang3.4 and gcc4.9. This is the result of the resolution to CWG issue 1288.

N3337包含以下用于列表初始化的语言:

N3337 contains the following language for list-initialization:

§8.5.4/ 3 [dcl.init.list]

§8.5.4/3 [dcl.init.list]


code> T 的定义如下:

- ...

- 否则,如果 T 是引用类型,则
T 引用的类型的prvalue临时变量列表初始化,并且引用绑定到临时

List-initialization of an object or reference of type T is defined as follows:
...
— 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

这当然意味着初始化 ar2 需要一个可访问的复制构造函数,因此会产生错误。

This, of course, means that the initialization of ar2 requires an accessible copy-constructor, hence the error.

在N3797中改变,其中从包含单个元素的初始化器列表的初始化优先于上面引用的情况。

The language has changed in N3797, where the initialization from an initializer list containing a single element takes precedence over the case quoted above.


- 否则,如果初始化器列表有一个 E T 不是引用类型或其引用类型与 E 引用相关,对象或引用被初始化从那个元素; ...

- 否则,如果 T 是引用类型,由 T 引用的类型是复制列表初始化或直接列表初始化,这取决于引用初始化的类型,并且引用绑定到该临时。

— 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; ...
— Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is copy-list-initialized or direct-list-initialized, depending on the kind of initialization for the reference, and the reference is bound to that temporary.

因此gcc 4.9和clang 3.4正在实现问题1288的解决方案,而gcc 4.8遵循C ++ 11标准。

So gcc 4.9 and clang 3.4 are implementing the resolution of issue 1288, while gcc 4.8 is following the wording in the C++11 standard.

这篇关于使用删除的拷贝构造函数初始化const引用成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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