临时绑定到引用是否需要C++中的复制构造函数

Does binding temporary to a reference require a copy constructor in C++?

本文关键字:C++ 复制 构造函数 绑定 引用 是否      更新时间:2023-10-16

考虑以下代码:

class A {
A(const A&);
public:
A() {}
};
int main() {
const A &a = A();
}

此代码在GCC 4.7.2中编译良好,但在Visual C++2010中编译失败,出现以下错误:

test.cc(8) : error C2248: 'A::A' : cannot access private member declared in class 'A'
test.cc(2) : see declaration of 'A::A'
test.cc(1) : see declaration of 'A'

那么,在将临时绑定到引用时,是否需要有一个可访问的复制构造函数?

这在一定程度上与我之前的问题有关:

有没有办法禁止将临时绑定到常量引用?

那么,在将临时绑定到引用时,是否需要有一个可访问的复制构造函数

C++11之后-否
C++11之前-是。


此代码与GCC 4.7.2一起编译良好,因为它符合C++11标准。

C++11标准规定,当从prvalue初始化常量引用时,它必须直接绑定到引用对象,并且不允许创建临时引用。此外,复制构造函数未被使用或是必需的。

在C++11之前,规则有所不同。这种行为(是否调用复制构造函数)是实现定义的。C++03允许在将常量引用绑定到临时时调用复制构造函数,因此在C++11之后,复制构造函数需要是可访问的。Visual C++2010遵循C++03标准。

C++03标准的第8.5.3.5节指出,这是实现定义的:

如果初始值设定项表达式是右值,其中T2是类类型,并且;cv1T1";是参考兼容的";cv2T2;引用以以下方式之一绑定(选择由实现定义):

--引用绑定到由右值表示的对象(见3.10)或该对象中的子对象。

--类型为";cv1T2";创建[sic],并调用构造函数将整个右值对象复制到临时对象中。引用绑定到临时对象或临时对象中的子对象。

将用于制作副本的构造函数应是可调用的,无论副本是否实际完成。

因此,这两种实现似乎都与C++03标准一致。

最后一句话有点令人困惑,但从我的阅读方式来看,这意味着实现可能会选择第二种方式,但仍然会优化掉副本。在这种情况下,即使复制实际上没有完成,复制构造函数也必须是可访问的,类似于返回值优化。

对于C++11标准,第二种方式不再是一种选择。

Visual C++不正确;标准没有指示复制构造函数必须是可访问的以将CCD_ 2引用绑定到临时的。