Lil*_*ard 28 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;
}
Run Code Online (Sandbox Code Playgroud)
问题是,v_even并且v_odd是对临时工具的非常规引用,这是不允许的.并尝试编译它会发出错误:
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)];
^ ~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我查看了所有在线提供的勘误表,没有任何内容涉及这个基本问题.我错过了什么吗?自从这本书被印刷以来,这方面的语言是否发生了变化(不太可能,因为该书本身提到了反对非常规的临时书的规则)?这里发生了什么?
如果我修改函数以使用值而不是引用,例如slice_array<double> v_even = ...,那么这实际上是编译的.然而,事实证明我的本地C++头使拷贝构造函数公众,而斯特劳斯和各种在线引用(cppreference.com,cplusplus.com)要求的拷贝构造函数是私有的.我认为这意味着这个解决方案是不可移植的.Stroustrup明确列出了一个带有非引用变量的代码示例,并说这会产生错误.
C++ 98规范(PDF)声明slice_array<T>具有私有拷贝构造函数.到2005年(根据这个规范),并且可能作为C++ 03的一部分,这变成了一个公共拷贝构造函数.
原始代码示例似乎存在几个不同的问题,以及本书中为许多运算符提供的声明.
我认为最好的解决方案是按照以下方式做
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;
}
Run Code Online (Sandbox Code Playgroud)
所有运算符slice_array<T>都被定义为const它们不是修改切片本身,而是修改内容.这些在书中被错误地定义为非const.