Passing rvalue as reference

What do you want to do with/to the object you are passing in?

When you take it as uint8Vect_t &dataBuff that should mean you want to make lasting modifications to it, which makes no sense if it is a temporary.

When you take it as uint8Vect_t const&dataBuff that should mean you want to copy from it and not modify it, which is probably what you want.

When you take it as uint8Vect_t dataBuff that should mean you need your own local temporary copy of it, to use as you wish and then throw away, and that should be important enough to be worth the cost of copying.

When you take it as uint8Vect_t &&dataBuff that should mean you want to make non lasting modifications (such as content stealing) from a temporary object that the caller is effectively promising to throw away after you are done with it.

That last choice is the one new in C++11 for passing rvalues.


When you use

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

the vector you pass into the function is a temporary object, and references can't bind to temporary objects.

The simple solution, if the function doesn't modify the argument, is to make it a reference to a constant object:

uint8Vect_t encodeData(uint8Vect_t const& dataBuff);

References to constant objects can bind to temporary objects.


Your issue is

uint8Vect_t encodeData(uint8Vect_t &dataBuff);

Here you are taking a reference to a uint8Vect_t. That works well with normal variables but uint8Vect_t(dataBlock.begin(), dataBlock.end()) is a temporary object and cannot be bound to lvalue reference.

If encodeData() does not change dataBuff then the simplest solution is to take a const & which can bind to a temproary.

uint8Vect_t encodeData(const uint8Vect_t &dataBuff);

If you have to change the contents of dataBuff then you would have to write another version of encodeData() that takes an rvalue reference

uint8Vect_t encodeData(uint8Vect_t &&dataBuff);

This will allow the function to bind to the temporary vector and you can work on it in the function as you would a normal vector.


I believe the reason you are seeing this is that your old compiler was a version of Microsoft Visual Studio. MSVS has a non standard extension that is on by default that allows temporary objects to bind to a lvalue reference. You can read more about it at: Non-const reference bound to temporary, Visual Studio bug?


Adding this to show you how you could change encodeData() to take an rvalue reference without having to write a new function.

#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 << " ";
}

Live Example

In the above example modify({ 1,2,3,4,5 }) calls modify(std::vector<int>&& foo) and then in the function foo is an lvaue. We then return the result of passing the "new" lvalue to modify(std::vector<int>& foo) which then returns a modified vector.