使用删除的拷贝构造函数初始化const引用成员 [英] Initialization of const reference member with deleted copy constructor
问题描述
这个代码,带有 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, ifT
is a reference type, a prvalue temporary of the type referenced byT
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 eitherT
is not a reference type or its referenced type is reference-related toE
, the object or reference is initialized from that element;...
— Otherwise, ifT
is a reference type, a prvalue temporary of the type referenced byT
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屋!