7

考虑以下代码:

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'

那么在将临时对象绑定到引用时是否有必要让复制构造函数可访问?

这与我之前的问题有些相关:

有没有办法禁用将临时绑定到 const 引用?

4

3 回答 3

4

那么在将临时对象绑定到引用时是否有必要让复制构造函数可访问?

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


这段代码在 GCC 4.7.2 中编译得很好,因为它符合 C++11 标准。

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

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

于 2012-12-16T05:23:40.527 回答
2

C++03 标准的第 8.5.3.5 节声明这是实现定义的:

如果初始化表达式是右值,T2 是类类型,并且“cv1 T1”与“cv2 T2”引用兼容,则引用以下列方式之一绑定(选择由实现定义):

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

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

无论复制是否实际完成,用于制作复制的构造函数都应该是可调用的。

所以看起来这两种实现都符合 C++03 标准。

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

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

于 2012-12-16T05:11:52.980 回答
0

Visual C++ 不正确;该标准并未表明必须可以访问复制构造函数才能将const引用绑定到临时对象。

于 2012-12-16T05:06:39.627 回答