[英]Passing rvalue as reference
我有一些Qt代码,我从我的svn repo下载。 我工作了一段时间,但我确信它曾用于编译。
我有一个新版本的Qt和编译器(就像我上次的那样)。 我目前的编译器是:mingw 4.9.2 32位。
所以这是我的问题代码:
QByteArray dataBlock = audioTestFile.read(PACKET_SIZE_TO_ENCODE);
// This line is the issue
uint8Vect_t testVect = encodeData(uint8Vect_t(dataBlock.begin(), dataBlock.end()));
哪里:
typedef std::vector<uint8_t> uint8Vect_t;
和
uint8Vect_t encodeData(uint8Vect_t &dataBuff);
所以你可以在这里看到我有一个函数encodeData(),它接受一个参数uint8Vect_t &
(pass by ref)。 我正在传递一个临时变量(我认为是一个rvalue),它是使用std :: vector构造函数(其中一个需要两个迭代器)从QByteArray dataBlock
迭代器(我测试过的)开始的。
但是,我收到错误:
../audioTest/txaudiostream.cpp:在成员函数'void CTxAudioStream :: playFile()':.. / audioTest / txaudiostream.cpp:212:94:错误:没有匹配函数来调用'CTxAudioStream :: encodeData(uint8Vect_t) )'uint8Vect_t testVect = encodeData(uint8Vect_t(dataBlock.begin(),dataBlock.end())); ^ ../audioTest/txaudiostream.cpp:212:94:注意:候选者是:.. / audioTest / txaudiostream.cpp:36:13:注意:uint8Vect_t CTxAudioStream :: encodeData(uint8Vect_t&)uint8Vect_t CTxAudioStream :: encodeData(uint8Vect_t&dataBuff) )^ ../audioTest/txaudiostream.cpp:36:13:注意:参数1从'uint8Vect_t {aka std :: vector}'到'uint8Vect_t&{aka std :: vector&}'没有已知的转换
基本上它是说我无法从uint8Vect_t转换为uint8Vect_t&。 但是如果我将uint8Vect_t类型的变量传递给函数(而不是contructor / temp变量的返回值),那么这就行了。
我认为在c ++ 11中你可以传递rvalues ..但我显然在这里遗漏了一些东西。 谁能解释一下:
你的问题是
uint8Vect_t encodeData(uint8Vect_t &dataBuff);
在这里您将参考uint8Vect_t
。 这适用于普通变量,但uint8Vect_t(dataBlock.begin(), dataBlock.end())
是一个临时对象,不能绑定到左值引用。
如果encodeData()
不改变dataBuff
那么最简单的解决方案是采用一个可以绑定到temproary的const &
。
uint8Vect_t encodeData(const uint8Vect_t &dataBuff);
如果你必须更改dataBuff
的内容,那么你必须编写另一个版本的encodeData()
,它接受一个右值参考
uint8Vect_t encodeData(uint8Vect_t &&dataBuff);
这将允许函数绑定到临时向量,您可以在函数中处理它,就像使用普通向量一样。
我相信你看到这个的原因是你的旧编译器是Microsoft Visual Studio的一个版本。 MSVS具有非标准扩展,默认情况下处于启用状态,允许临时对象绑定到左值引用。 您可以在以下位置阅读更多相关信息: 非const引用绑定到临时,Visual Studio错误?
添加它以向您展示如何更改encodeData()
以获取右值引用而无需编写新函数。
#include <iostream>
#include <vector>
std::vector<int> modify(std::vector<int>& foo)
{
for (auto & e : foo)
e *= 2;
return foo;
}
std::vector<int> modify(std::vector<int>&& foo)
{
return modify(foo);
}
int main()
{
std::vector<int> foo = modify({ 1,2,3,4,5 });
for (const auto & e : foo)
std::cout << e << " ";
}
在上面的例子中, modify({ 1,2,3,4,5 })
调用modify(std::vector<int>&& foo)
,然后在函数foo
中调用lvaue。 然后我们返回传递“new”左值的结果来modify(std::vector<int>& foo)
,然后返回修改后的向量。
当你使用
encodeData(uint8Vect_t(dataBlock.begin(), dataBlock.end()))
传递给函数的向量是临时对象,引用不能绑定到临时对象。
如果函数不修改参数,那么简单的解决方案是使它成为对常量对象的引用:
uint8Vect_t encodeData(uint8Vect_t const& dataBuff);
对常量对象的引用可以绑定到临时对象。
你想对你传入的对象做什么?
当你把它作为uint8Vect_t &dataBuff
,你应该意味着要对它进行持久的修改,如果它是暂时的,这是没有意义的。
当你把它作为uint8Vect_t const&dataBuff
,它应该意味着你想要从它复制而不是修改它, 这可能是你想要的 。
当你把它作为uint8Vect_t dataBuff
,这意味着你需要你自己的本地临时副本,按你的意愿使用,然后丢弃,这应该是重要的,值得复制的成本。
当你把它作为uint8Vect_t &&dataBuff
,你应该意味着你要从一个临时对象进行非持久性修改(例如内容窃取),调用者有效地承诺在完成它之后将其丢弃。
最后一个选择是C ++ 11中用于传递rvalues的新选项。
任何函数的返回值都是临时对象(rvalue),您不能将临时对象作为引用传递。
下面的代码将生成相同的错误,因为我们试图将“saurabh”(临时对象)作为引用类型传递。
即
void fun(string& name){
//statements;
}
int main(){
fun("Saurabh");
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.