传递右值作为引用
Passing rvalue as reference
我有一些从svn存储库下载的Qt代码。自从我研究它以来已经有一段时间了,但我确信它曾经编译过。
我有一个新版本的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 &
(通过 ref 传递(。我正在从QByteArray dataBlock
迭代器(我已经测试过(中传递一个使用 std::vector 构造函数(其中一个需要两个迭代器(创建的临时变量(我认为是右值(。
但是,我收到错误:
../audioTest/txaudiostream.cpp:在成员函数中 'void CTxAudioStream::p layFile((': ../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 类型的变量传递到函数中(而不是构造器/temp 变量的返回值(,那么这就可以了。
我以为在 c++11 中你可以传递右值......但我显然在这里遗漏了一些东西。谁能解释一下:
- 为什么这是错误的?
- 什么是高效/优雅(可读(的解决方案?
你的问题是
uint8Vect_t encodeData(uint8Vect_t &dataBuff);
在这里,您正在引用uint8Vect_t
. 这适用于普通变量,但uint8Vect_t(dataBlock.begin(), dataBlock.end())
是一个临时对象,不能绑定到左值引用。
如果encodeData()
没有改变dataBuff
那么最简单的解决方案是采用可以绑定到临时const &
。
uint8Vect_t encodeData(const uint8Vect_t &dataBuff);
如果必须更改dataBuff
的内容,则必须编写另一个采用右值引用的encodeData()
版本
uint8Vect_t encodeData(uint8Vect_t &&dataBuff);
这将允许函数绑定到临时向量,您可以在函数中像处理普通向量一样处理它。
我相信你看到这个的原因是你的旧编译器是Microsoft Visual Studio的一个版本。 MSVS 具有默认启用的非标准扩展,允许临时对象绑定到左值引用。 您可以在以下位置阅读有关它的更多信息:绑定到临时的 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 中用于传递右值的新选择。
任何函数的返回值都是临时对象(rvalue(,不能将临时对象作为引用传递。
下面的代码将生成与我们尝试传递"saurabh"(temp 对象(作为引用类型相同的错误。
即
void fun(string& name){
//statements;
}
int main(){
fun("Saurabh");
return 0;
}
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 编译C++时未定义的引用
- Ctypes wstring通过引用传递
- c++r值引用应用于函数指针
- 理解c++中的引用
- C++取消引用指针.为什么会发生变化
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 强制转换为引用类型
- 引用一个已擦除类型(void*)的指针
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 具有默认值的引用获取函数
- 如何使用基类指针引用派生类成员
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 如何引用基类的派生类?