当前位置:  开发笔记 > 编程语言 > 正文

传递右值作为参考

如何解决《传递右值作为参考》经验,为你挑选了2个好方法。

我有一些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 uint8Vect_t;

uint8Vect_t encodeData(uint8Vect_t &dataBuff);

所以你可以在这里看到我有一个函数encodeData(),它接受一个参数uint8Vect_t &(通过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 ..但我显然在这里遗漏了一些东西.谁能解释一下:

    为什么这是错的?

    什么是高效/优雅(可读)的解决方案?

NathanOliver.. 13

你的问题是

uint8Vect_t encodeData(uint8Vect_t &dataBuff);

在这里你参考了一个uint8Vect_t.这适用于普通变量但是uint8Vect_t(dataBlock.begin(), dataBlock.end())是临时对象,不能绑定到左值引用.

如果encodeData()不改变,dataBuff那么最简单的解决方案是采取一个const &可以绑定到temproary.

uint8Vect_t encodeData(const uint8Vect_t &dataBuff);

如果你必须改变那里的内容,dataBuff你将不得不写另一个版本encodeData()的rvalue引用

uint8Vect_t encodeData(uint8Vect_t &&dataBuff);

这将允许函数绑定到临时向量,您可以在函数中处理它,就像使用普通向量一样.


我相信你看到这个的原因是你的旧编译器是Microsoft Visual Studio的一个版本.MSVS具有非标准扩展,默认情况下处于启用状态,允许临时对象绑定到左值引用.您可以在以下位置阅读更多相关信息:非const引用绑定到临时,Visual Studio错误?


添加此项以向您展示如何在encodeData()不必编写新函数的情况下更改为rvalue引用.

#include 
#include 

std::vector modify(std::vector& foo)
{
    for (auto & e : foo)
        e *= 2;
    return foo;
}

std::vector modify(std::vector&& foo)
{
    return modify(foo);
}


int main()
{
    std::vector foo = modify({ 1,2,3,4,5 });
    for (const auto & e : foo)
        std::cout << e << " ";
}

Live Example

在上面的例子中,modify({ 1,2,3,4,5 })调用modify(std::vector&& foo)然后在函数中foo是一个lvaue.然后我们返回传递"new"左值的结果来修改(std :: vector&foo),然后返回修改后的向量.



1> NathanOliver..:

你的问题是

uint8Vect_t encodeData(uint8Vect_t &dataBuff);

在这里你参考了一个uint8Vect_t.这适用于普通变量但是uint8Vect_t(dataBlock.begin(), dataBlock.end())是临时对象,不能绑定到左值引用.

如果encodeData()不改变,dataBuff那么最简单的解决方案是采取一个const &可以绑定到temproary.

uint8Vect_t encodeData(const uint8Vect_t &dataBuff);

如果你必须改变那里的内容,dataBuff你将不得不写另一个版本encodeData()的rvalue引用

uint8Vect_t encodeData(uint8Vect_t &&dataBuff);

这将允许函数绑定到临时向量,您可以在函数中处理它,就像使用普通向量一样.


我相信你看到这个的原因是你的旧编译器是Microsoft Visual Studio的一个版本.MSVS具有非标准扩展,默认情况下处于启用状态,允许临时对象绑定到左值引用.您可以在以下位置阅读更多相关信息:非const引用绑定到临时,Visual Studio错误?


添加此项以向您展示如何在encodeData()不必编写新函数的情况下更改为rvalue引用.

#include 
#include 

std::vector modify(std::vector& foo)
{
    for (auto & e : foo)
        e *= 2;
    return foo;
}

std::vector modify(std::vector&& foo)
{
    return modify(foo);
}


int main()
{
    std::vector foo = modify({ 1,2,3,4,5 });
    for (const auto & e : foo)
        std::cout << e << " ";
}

Live Example

在上面的例子中,modify({ 1,2,3,4,5 })调用modify(std::vector&& foo)然后在函数中foo是一个lvaue.然后我们返回传递"new"左值的结果来修改(std :: vector&foo),然后返回修改后的向量.



2> Some program..:

当你使用

encodeData(uint8Vect_t(dataBlock.begin(), dataBlock.end()))

传递给函数的向量是临时对象,引用不能绑定到临时对象.

如果函数不修改参数,那么简单的解决方案是使它成为对常量对象的引用:

uint8Vect_t encodeData(uint8Vect_t const& dataBuff);

对常量对象的引用可以绑定到临时对象.

推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有