【问题标题】:Reference collapsing?参考崩溃?
【发布时间】:2010-09-22 16:02:07
【问题描述】:

通过尝试解决this problem,有些事情让我感到奇怪。考虑以下代码:

template <typename T>
struct foo 
{
    foo(T const& x) : data(x) {}
    T data;
};

看来我可以毫无错误地构造foo&lt;T const&amp;&gt; 类型的对象,假设的T const&amp; const&amp; 被理解为T const&amp;

这似乎也称为 reference collapsing,但我之前从未听说过这个术语(请参阅链接问题中的 cmets)。

这很普遍吗?这是标准吗?

【问题讨论】:

标签: c++


【解决方案1】:

在 C++03 中,执行以下操作是不合法的

typedef int &ref;
ref &r = ...; // reference to reference!

这经常会给使用非常严格或更旧的 C++03 编译器(GCC4.1 和 Comeau 8/4/03 不喜欢上述)的人带来问题,因为标准函数对象绑定器不处理“引用到引用”的情况,偶尔会创建这样的非法类型。

在 C++0x 中,这称为“引用折叠”,是的。大多数当前的 C++03 编译器通过追溯应用规则来做到这一点(即T&amp;,其中T 表示引用类型再次为T)。 boost.call_traits 库使得声明此类函数参数变得很容易,因此不会发生“引用引用”的情况。

请注意那里的const 没有任何作用。应用在引用类型上的 const 会被静默忽略。所以即使编译器支持引用折叠,下面的也是不合法的

int const x = 0;

// illegal: trying to bind "int&" to "int const"!
ref const& r = x; 

【讨论】:

  • 太好了,我发现这可以通过特征类来解决,但我在 [我的 STL 实现] 中从未见过这样的事情。
  • 不应该是“即T&amp;,其中T表示引用类型又是T&amp;”?
  • @Fred 这将是自递归的。我的意思是,如果TU&amp;,而你说T&amp;,则结果类型是T - 即U&amp;。当然,这与右值引用不兼容。我需要说“即T&amp;,其中T 表示类型U &amp;-or-&amp;&amp; 表示类型U &amp;”,以正确使用右值引用。
【解决方案2】:

根据this,在 C++98 中仅对引用折叠的支持有限:

在 C++98 中,只有一个引用 折叠规则:T& & 或参考 引用,折叠为 T&:

void g(int & ri) {++ri;} // int& & -> int& 
void f(int & ri) {g(ri);}

即便如此,尝试声明一个引用引用的变量也是非法的:

int ben;
int& bill(ben);     // OK
int & & bob(bill);  // error C2529: 'bob' : reference to reference is illegal

【讨论】:

  • C++03 中没有引用折叠。那篇文章的作者被误导了。使用引用名称的标识表达式的类型不是引用类型。 No 表达式具有引用类型。表达式具有决定它们如何绑定到引用的值类别。
  • @Potatoswatter - 谢谢,现在也有更好的参考。我会删除这部分。
  • 谢谢……但是,那个链接不是我之前关注的。
  • @Potatoswatter - 我删除了一个指向 C++03 的 MSDN 链接
  • 您删除的链接不是我在第一条评论中提到的那个。这个例子是错误的;函数调用g( ri ) 不涉及任何形式的折叠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多