Stroustrup如何将非const引用作为临时引用?

时间:2012-08-14 06:14:27

标签: c++ reference language-lawyer

在Stroustrup的C ++编程语言书(第3版)中,在Numerics一章中,他展示了以下代码片段:

void f(valarray<double>& d)
{
    slice_array<double>& v_even = d[slice(0,d.size()/2,2)];
    slice_array<double>& v_odd = d[slice(1,d.size()/2,2)];

    v_odd *= v_even;
    v_even = 0;
}

问题是,v_evenv_odd是对临时对象的非const引用,这是不允许的。并且尝试编译它会发出错误:

error: non-const lvalue reference to type 'slice_array<double>' cannot bind to a temporary of type 'slice_array<double>'
    slice_array<double>& v_even = d[slice(0,d.size()/2,2)];
                         ^        ~~~~~~~~~~~~~~~~~~~~~~~~

我查看了所有在线提供的勘误表,没有任何内容涉及这个基本问题。我错过了什么吗?自从这本书被印刷以来,这方面的语言是否发生了变化(不太可能,因为该书本身提到了反对非常规的临时书的规则)?这是怎么回事?


如果我修改函数以使用值而不是引用,例如slice_array<double> v_even = ...,然后这实际上编译。但是,事实证明我的本地C ++标头使复制构造函数公开,而Stroustrup和各种在线引用(cppreference.com,cplusplus.com)声称复制构造函数是私有的。我认为这意味着这个解决方案是不可移植的。 Stroustrup明确列出了一个带有非引用变量的代码示例,并说这会产生错误。


C ++ 98规范(PDF)将slice_array<T>声明为具有私有拷贝构造函数。到2005年(根据this spec),并且可能是C ++ 03的一部分,这改为公共拷贝构造函数。

2 个答案:

答案 0 :(得分:9)

原始代码示例似乎存在几个不同的问题,以及本书中为许多运营商提供的声明。

我认为应该做的“最佳”解决方案如下

void f(valarray<double>& d)
{
    const slice_array<double>& v_even = d[slice(0,d.size()/2,2)];
    const slice_array<double>& v_odd = d[slice(1,d.size()/2,2)];

    v_odd *= v_even;
    v_even = 0;
}

slice_array<T>上的所有运算符都定义为const,因为它们不是修改切片本身,而是修改内容。这些在本书中被错误地定义为非const

答案 1 :(得分:4)

这似乎是在勘误表中发表的(虽然链接已经死了)。

然而谷歌很棒,它显示了像“slice_array&amp; v_even”这样的搜索的快照

  

Stroustrup:用于C ++编程的第三次打印的勘误语言
  www.research.att.com/~bs/3rd_printing4.html
  [缓存] [分享]在Google+上分享。
  查看帖子。
  你公开为此+1了   撤消

void f(valarray<double>& d)
{
    slice_array<double>& v_even = d[slice(0,d.size()/2, 2)];
    slice_array<double>& v_odd  = d[slice(1,d.size()/2,2)];

    v_odd *= 2; // double ...

编辑: - 感谢有问题的凯文编辑,这不再是一个错误 我可以在N3092中清楚地看到(§26.6.1,Pg 944)

  

4. 应提供引入此类替代类型的实施方案   附加功能和操作符如下:
- 适用于每一个   功能采用const valarray&amp;相同的功能   应增加更换类型;
- 每个功能需要两个   const valarray&amp;参数,相同的功能   const valarray&amp;的组合和更换类型   加入。

     

5. 特别是,实现应允许valarray   由这些替换类型构成,并允许分配   并计算这些类型的分配给valarray, slice_array,   gslice_array,mask_array和indirect_array对象。

此外,我的编译器没有给出任何问题(目前VS 2010)与代码,编译完美。