C++ 传递右值作为引用
我有一些Qt代码,我从我的svn repo下载。我已经有一段时间没做了,但我确信它曾经被编译过 我有一个新版本的Qt和编译器(和上次一样)。我当前的编译器是:mingw4.9.2 32位 这是我的问题代码:C++ 传递右值作为引用,c++,qt,c++11,rvalue-reference,C++,Qt,C++11,Rvalue Reference,我有一些Qt代码,我从我的svn repo下载。我已经有一段时间没做了,但我确信它曾经被编译过 我有一个新版本的Qt和编译器(和上次一样)。我当前的编译器是:mingw4.9.2 32位 这是我的问题代码: QByteArray dataBlock = audioTestFile.read(PACKET_SIZE_TO_ENCODE); // This line is the issue uint8Vect_t testVect = encodeData(uint8Vect_t(dataBloc
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;
您可以在这里看到,我有一个函数encodeData(),它接受一个参数uint8Vect\u t&
(passbyref)。我正在传递一个临时变量(我认为是一个右值),该变量是使用std::vector构造函数(其中一个构造函数使用两个迭代器)从QByteArray数据块
迭代器(我已经测试过了)创建的
但是,我得到了一个错误:
../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&)uint8Vect
CTxAudioStream::encodeData(uint8Vect\u t&dataBuff)
^../audioTest/txaudiostream.cpp:36:13:注意:参数1没有从'uint8Vect_t{aka std::vector}'到'uint8Vect_t&{aka std::vector&}'的已知转换
基本上是说我不能从uint8Vect\u t转换到uint8Vect\u t&。但是,如果我将uint8Vect_t类型的变量传递到函数中(而不是constructor/temp变量的返回值),那么这一切正常
我认为在c++11中可以传递右值。。但我显然遗漏了一些东西。谁能解释一下:
您想对正在传递的对象做什么 当您将其视为
uint8Vect\u t&dataBuff
时,这应该意味着您希望对其进行持久的修改,如果它是临时的,则没有任何意义
当您将其视为uint8Vect_t const&dataBuff
时,这意味着您希望从它复制而不是修改它,这可能就是您想要的
当您将其视为uint8Vect_t dataBuff
时,这意味着您需要自己的本地临时副本,可以随意使用,然后扔掉,这一点非常重要,值得复制
当您将其视为uint8Vect\t&&dataBuff
时,这意味着您希望对临时对象进行非持久的修改(例如内容窃取),调用方实际上承诺在处理完该对象后将其丢弃
最后一个选项是C++11中用于传递右值的新选项
encodeData(uint8Vect_t(dataBlock.begin(), dataBlock.end()))
传递到函数中的向量是临时对象,引用不能绑定到临时对象
如果函数不修改参数,简单的解决方案是将其作为常量对象的引用:
对常量对象的引用可以绑定到临时对象。您的问题是
uint8Vect_t encodeData(uint8Vect_t &dataBuff);
这里是对uint8Vect\t
的引用。这可以很好地处理普通变量,但是uint8Vect\t(dataBlock.begin(),dataBlock.end())
是一个临时对象,不能绑定到左值引用
如果encodeData()
uint8Vect_t encodeData(const uint8Vect_t &dataBuff);
如果必须更改dataBuff
的内容,则必须编写另一个版本的encodeData()
,该版本采用右值引用
uint8Vect_t encodeData(uint8Vect_t &&dataBuff);
这将允许函数绑定到临时向量,您可以像处理法向量一样在函数中处理它
我相信您看到这一点的原因是您的旧编译器是Microsoft Visual Studio的一个版本。MSVS有一个默认启用的非标准扩展,允许临时对象绑定到左值引用。您可以通过以下网址了解更多信息:
添加此代码向您展示如何更改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 << " ";
}
#包括
#包括
std::vector modify(std::vector和foo)
{
适用于(自动和电气:foo)
e*=2;
返回foo;
}
std::vector modify(std::vector&&foo)
{
返回修改(foo);
}
int main()
{
std::vector foo=modify({1,2,3,4,5});
用于(const auto&e:foo)
std::cout任何函数的返回值都是临时对象(右值),不能将临时对象作为引用传递。
下面的代码将生成与我们尝试将“saurabh”(temp对象)作为引用类型传递时相同的错误
i、 e
您的旧编译器是什么?MSVS?您不能通过非常量引用传递临时(右值)。根据您期望的语义(所有权、可变性等),可以通过值传递,也可以通过常量引用传递@NathanOliver很有可能是这样的,我当时正在处理大量不同的编译器…但我不能100%肯定…会有区别吗?当然,它的语法是正确的还是错误的?(不是学究,这是一个严肃的问题)代码是错误的,所以它以前编译的事实告诉我们,以前的编译器很可能是MSVC(它编译了错误代码的特定示例)。@code\u fodder我在我的答案中添加了一个解释。好吧,我想我现在明白了(从你的答案和其他注释中)…const的事情现在似乎很明显了(在解释之后!),+1刚刚重新检查过……我正在修改dataBuf,所以我想我需要通过移动或复制来传递。@code\u fodder那么基本上有两种解决方案:创建一个临时变量并将其传递给函数,或者创建t
uint8Vect_t encodeData(uint8Vect_t &&dataBuff);
#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 << " ";
}
void fun(string& name){
//statements;
}
int main(){
fun("Saurabh");
return 0;
}