意外的const引用行为 [英] Unexpected const reference behavior

查看:126
本文介绍了意外的const引用行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include <iostream>

class A { 
  public:  
    A(){ cerr << "A Constructor" << endl; }  
    ~A(){ cerr << "A Destructor" << endl; }  
    A(const A &o){ cerr << "A Copy" << endl; } 
    A& operator=(const A &o){ cerr << "A Assignment" << endl; return *this; }
};


class B : public A { 
  public:  
    B() : A() { cerr << "B Constructor" << endl; }  
    ~B(){ cerr << "B Destructor" << endl; }
  private:
    B(const B &o) : A() { cerr << "B Copy" << endl; } 
    B& operator=(const B &o){ cerr << "B Assignment" << endl; return *this; }
};

int main() {  
  A a;  
  const A &b = B();  
  return 0; 
}

在GCC 4.2中,我收到以下消息:

In GCC 4.2, I get this message:

In function 'int main()':
Line 16: error: 'B::B(const B&)' is private
compilation terminated due to -Wfatal-errors.

如果我从B中删除私有,我得到我期望的输出:

If I remove the "private" from B, I get the output I expect:

A Constructor
A Constructor
B Constructor
B Destructor
A Destructor
A Destructor

我的问题是:为什么做一个不被调用的方法private编译?这是标准规定吗?是否有解决方法?

My question is: why does making a method which isn't called private change whether this code compiles? Is this standard-mandated? Is there a workaround?

推荐答案

当前标准(C ++ 03)中的重要语句似乎在§8.5。 3,它解释了如何初始化引用(在这些引号中, T1 是被初始化的引用的类型, T2 是初始化器表达式的类型。)

The important verbiage in the current standard (C++03) seems to be in §8.5.3, which explains how references are initialized (In these quotes, T1 is the type of the reference being initialized and T2 is the type of the initializer expression).


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

If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation-defined):

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

-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

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

-- A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

将用于创建副本的构造函数可调用无论副本

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

因此,即使实现将引用直接绑定到临时对象,复制构造函数也必须可访问。

So, even if the implementation binds the reference directly to the temporary object, the copy constructor must be accessible.

请注意,在C ++ 0x中,根据 CWG缺陷391 。新语言(N3092§8.5.3):

Note that this is changed in C++0x, per the resolution of CWG defect 391. The new language reads (N3092 §8.5.3):


否则,如果 T2 是类类型,

- 初始化器表达式是一个右值, cv1 T1 兼容 cv2 T2

-- the initializer expression is an rvalue and "cv1 T1" is reference-compatible with "cv2 T2,"

- T1 T2 没有引用相关,初始化器表达式可以隐式转换为类型 cv3 T3的右值(通过枚举适用的转换函数(13.3.1.6)并通过重载解析(13.3)选择最佳转换函数来选择此转换),

-- T1 is not reference-related to T2 and the initializer expression can be implicitly converted to an rvalue of type "cv3 T3" (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6) and choosing the best one through overload resolution (13.3)),

到第一种情况下的初始化器表达式rvalue和第二种情况下的转换结果的对象(或者在任一种情况下,到对象的适当的基类子对象)。

then the reference is bound to the initializer expression rvalue in the first case and to the object that is the result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).

第一种情况适用,引用是直接绑定到初始化器表达式。

The first case applies and the reference is "bound directly" to the initializer expression.

这篇关于意外的const引用行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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