Mat*_*ner 13 c++ gcc rvalue-reference c++11
在以下代码行中:
bootrec_reset(File(path, size, off), blksize);
Run Code Online (Sandbox Code Playgroud)
用原型调用函数:
static void bootrec_reset(File &file, ssize_t blksize);
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
libcpfs/mkfs.cc:99:53:错误:从'File'类型的右值开始无效初始化'File&'类型的非const引用
libcpfs/mkfs.cc:30:13:错误:传递'void bootrec_reset(File&,ssize_t)'的参数1
我知道你不能const &
根据标准将非const引用()传递给rvalues.但是,MSVC允许您这样做(请参阅此问题).这个问题试图解释为什么,但答案没有意义,因为他正在使用文字的引用,这是一个极端的案例,显然应该被禁止.
在给定的示例中,可以清楚地看到将发生以下事件顺序(就像在MSVC中一样):
File
的构造函数将被调用.File
,和blksize
,被推入堆栈.bootrec_reset
利用file
.bootrec_reset
,临时File
被摧毁.有必要指出File
引用需要是非const的,因为它是文件的临时句柄,在其上调用非const方法.此外,我不想将File
构造函数参数传递bootrec_reset
给那里构造,也没有任何理由File
在调用者中手动构造和销毁对象.
所以我的问题是:
是的,普通函数不能将非const引用绑定到临时函数 - 但方法可以 - 总是让我烦恼.TTBOMK的基本原理是这样的(源自这个comp.lang.c ++.主持线程):
假设你有:
void inc( long &x ) { ++x; }
void test() {
int y = 0;
inc( y );
std::cout << y;
}
Run Code Online (Sandbox Code Playgroud)
如果你允许long &x
参数inc()
绑定到一个临时long
副本y
,那么这段代码显然不能达到预期的效果 - 编译器只会静默生成y
不变的代码.显然,这是C++早期的常见错误来源.
如果我设计了C++,我的偏好是允许非const引用绑定到temporaries,但禁止在绑定到引用时从左值到临时值的自动转换.但谁知道,这可能会开辟出一种不同的蠕虫......
相反惯例的实际经验,这是事情最初的运作方式.C++在很大程度上是一种进化的语言,而不是一种设计的语言.很大程度上,那些仍然存在的规则是有效的(虽然1998年的标准化发生了一些大的例外,例如臭名昭着export
的委员会发明而不是标准化现有的做法).
对于绑定规则,不仅具有C++的经验,而且还具有与Fortran等其他语言类似的经验.
正如@j_random_hacker在他的回答中指出的那样(正如我写的那样得分为0,表明SO中的得分确实不能作为衡量质量的标准),最严重的问题与隐式转换和重载解决有关.
你不能.
代替 ...
bootrec_reset(File(path, size, off), blksize);
Run Code Online (Sandbox Code Playgroud)
......写...
File f(path, size, off);
bootrec_reset(f, blksize);
Run Code Online (Sandbox Code Playgroud)
或者定义适当的重载bootrec_reset
.或者,如果"聪明"代码有吸引力,您原则上可以编写,您可以在bootrec_reset(tempref(File(path, size, off)), blksize);
其中简单地定义tempref
以适当地返回其参数引用.但即使这是一种技术解决方案,也不要.
不,没有任何改变给定代码的东西.
但是,如果您愿意重写,那么您可以使用例如C++ 0x右值引用或上面显示的C++ 98变通方法.
干杯&hth.,
即将推出的C++ 0x标准是否会改变这一点,或者新标准是否在这里提供了更合适的内容,例如所有关于rvalue引用的乱码?
是.由于每个名称都是左值,因此将任何表达式视为左值几乎是微不足道的:
template <typename T>
T& as_lvalue(T&& x)
{
return x;
}
// ...
bootrec_reset(as_lvalue(File(path, size, off)), blksize);
Run Code Online (Sandbox Code Playgroud)