What is the purpose of rvalue reference to an array in C ++ 11?

Arrays cannot be returned by a value from a function (only by reference / constant reference) in both C ++ 03 and C ++ 11 (because we cannot directly assign one array to another):

const size_t N = 10;
using Element = int;
using Array = Element[N];

Array array;

// does not compile
// Array GetArray()
// {
//     return array;
// }

Array& GetArrayRef()
{
    return array;
}

In C ++, a new reference type was introduced - rvalue reference. It can also be used with arrays:

void TakeArray(Array&& value)
{
}

// ...

TakeArray(std::forward<Array>(array));
TakeArray(std::forward<Array>(GetArrayRef()));

What is the purpose of such a reference (rvalue reference to an array)? Can it be used in any real code or is it just a defect of the C ++ 11 standard?

+4
source share
4 answers

rvalue , 1 , , , ( ).

vector , move vector .

, .

std::vector<int> data[1000];
void populate_data() {
  for( auto& v : data )
    v.resize(1000);
}
template<std::size_t N>
std::vector< std::vector<int> > get_data( std::vector<int>(&&arr)[N] ) {
  std::vector< std::vector<int> > retval;
  retval.reserve(N);
  for( auto& v : arr )
    retval.emplace_back( std::move(v) );
  return retval;
}
template<std::size_t N>
std::vector< std::vector<int> > get_data( std::vector<int>(const&arr)[N] ) {
  std::vector< std::vector<int> > retval;
  retval.reserve(N);
  for( auto const& v : arr )
    retval.emplace_back( v );
  return retval;
}
int main() {
  populate_data();
  auto d = get_data(data); // copies the sub-vectors
  auto d2 = get_data( std::move(data) ); // moves the sub-vectors
}

, move d . rvalue -, move d ( rvalue) .

, . , rvalue (aka owning range), , move . .


1 , "" , , , , . ( , ++ 11 pre-++ 11, ). rvalue cast. , , " ", , , rvalue "" , . rvalue swap , , , .

+5

r- - :

  • , ,
  • , ()

++ , , , C void func(int a[5]), 2 ( ).

r-value :

  • ; , r- , restrict

, , .

+2

This is hardly a defect; it introduces an exciting ability to move objects to the target. This means that the target descriptor is exchanged for a source that will soon exit the system.

+1
source

It is not entirely true that you cannot have time series of an array. You can

void f(const std::string(&&x)[2]) {
   std::cout << "rvalue" << std::endl;
}

void f(const std::string(&x)[2]) {
   std::cout << "lvalue" << std::endl;
}

template<typename T>
using id = T;

int main() {
  f(id<std::string[]>{"Hello", "Folks"});
  f(id<std::string const[]>{"Hello", "Folks"});

  std::string array[] = { "Hello", "Folks" };
  std::string const arrayConst[] = { "Hello", "Folks" };
  f(array);
  f(arrayConst);
}

Starting with C ++ 14, you are also allowed to pass an enumerated initialization list directly to rvalue overload

f({ "Hello", "Folks" });
+1
source

Source: https://habr.com/ru/post/1532852/


All Articles