C++ 传递右值作为引用

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

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