[英]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值引用的好處不那么直接:
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.