簡體   English   中英

在C ++ 11中對rvalue引用數組的目的是什么?

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

在C ++ 03和C ++ 11中,數組不能通過函數(僅通過引用/常量引用)返回數組(因為我們不能直接將一個數組分配給另一個數組):

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

在C ++中引入了一個新的引用類型 - 右值引用。 它也可以用於數組:

void TakeArray(Array&& value)
{
}

// ...

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

這種引用的目的是什么(rvalue引用數組)? 它可以用在任何實際代碼中,還是僅僅是C ++ 11標准的缺陷?

右值引用是程序員或編譯器的承諾,即所引用的數據將被處理為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與否。 如果整個容器從(右值參考) move d,則rvalue覆蓋執行子數據的move ,否則執行復制。

通過更多的工作,我們可以編寫上面的內容,以便一切都在一個方法中發生。 因此,如果我們有一個右值容器(也就是擁有范圍),並且容器本身不適合直接move ,我們move內容。 但這只是高級元編程,而不是答案的必要條件。


1編譯器在受限制的情況下執行此操作,涉及在使用后“無法”引用的對象,因為它是匿名臨時的,或者因為它在某些情況下在函數的返回值中使用。 (實際上這不是不可能的,理論上這個C ++ 11特性可能會破壞前C ++ 11代碼,但它非常接近)。 程序員通過右值轉換來執行此操作。 它究竟意味着它將“立即處置”取決於上下文,但一般規則是rvalue引用的使用者可以將對象置於任何仍然可以被銷毀和交互的“有效”狀態。 基於rvalue的swap的存在意味着將其置於只能被銷毀的狀態是不安全的。

r值參考是兩件事:

  • 這是一個參考,所有這一切都需要
  • 它是對編譯器的承諾,所引用的對象是未命名的(臨時的)或可以這樣對待

在C ++中,通過引用傳遞數組允許,尤其是確保其長度,與C的void func(int a[5])相比,這已經是一個改進,其中傳遞長度為2的數組是完全可以接受的(盡管編譯器很好)會警告)。

然而,對數組的r值引用的好處不那么直接:

  • 一個未命名的對象不能別名; 因此,r值引用必然沒有別名,就好像已經指定了restrict
  • 警告調用者可以移動數組的元素

因此,即使使用數組,也可以進行優化。

你不能擁有數組臨時表並不完全正確。 您可以

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);
}

從C ++ 14開始, 您還可以將支持的init列表直接傳遞給rvalue重載

f({ "Hello", "Folks" });

它幾乎不是缺陷 ,它引入了物體移動到目標的令人興奮的能力。 這意味着目標句柄被交換為即將超出范圍的源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM