[英]Why does function return not move vector?
經過很長時間的C#工作后,我正在使用C ++ 17,並通過一些Euler問題解決了我的問題。 無論如何,任何人都可以解釋為什么createRandomVector(const int n)
沒有“移動”創建的向量嗎? 我輸出內存地址,並且它們僅在通過引用傳遞時保持不變(很明顯)。 下面是代碼:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <random>
using namespace std;
auto createRandomVector(const int n)
{
vector<int> v(n);
iota(begin(v), end(v), 1);
shuffle(begin(v), end(v), std::mt19937());
cout << &v << endl;
return v;
}
void printVector(const vector<int>& v, ostream& os);
int main()
{
auto v = createRandomVector(100);
printVector(v, cout);
cout << endl;
cout << &v << endl;
return 0;
}
void printVector(const vector<int>& v, ostream& os)
{
cout << &v << endl;
for_each(begin(v), end(v), [&os](auto& i)
{
os << i << " ";
});
}
這是輸出:
00BBFC20
00BBFD38
100 73 64 ... 85 90
00BBFD38
為什么第一存儲器地址與第二存儲器地址不匹配? 我對移動在現代C ++中的工作方式有一些了解(static_cast)。 但是為什么這不起作用?
這里有兩個問題:移動和復制省略。
首先,移動: 移動意味着存在兩個不同的對象,並且其中一個的內容轉移到了另一個。 (與將一個內容復制到另一個內容相反)。 在C ++中,對象在整個生命周期中都有固定的地址。
示例片段:
vector<int> a { 1, 2, 3, 4, 5 };
vector<int> b;
cout << &a << ", " << &a[0] << '\n';
b = std::move(a);
cout << &b << ", " << &b[0] << '\n';
我沒有運行此命令,因此希望它沒有錯別字,但您應該看到,即使兩個向量不同, int
對象塊也已從一個轉移到另一個。
如果將&v[0]
的輸出添加到程序中,則應該會看到相同的效果。
其次, 復制省略 。 在這種情況下,C ++標准使其成為可選,以便在為main
v
預留的存儲空間中實際創建createRandomVector
的局部變量v
。 在這種情況下,甚至沒有任何與return
步驟相關的移動或復制操作。
當函數按值返回並且return語句的形式為: return X;
可能發生的情況return X;
其中X
是沒有修飾的局部變量的名稱。
如果編譯器確實采用了此選項,則程序的前兩個輸出將是相同的。 顯然,您的編譯器僅決定在發布模式下執行此操作。
為什么第一存儲器地址與第二存儲器地址不匹配?
它們是不同的對象,因此不需要它們具有相同的內存地址。
但是,第二個對象可能會重用第一個對象的存儲。 這種優化-即構造局部自動變量來代替返回值,從而從局部變量中消除(通過移動)其副本初始化-被稱為返回值優化 。
雖然返回值本身是一個臨時值,但在調用范圍內還有一個從臨時值到局部變量的移動。
此舉也可以忽略。
編輯:自C ++ 17起不再適用。
因此,另一種回答你的問題是:由於編譯器沒有執行
任何
命名返回值優化
,或者它不從的Elid返回值的舉動。
這樣的優化不是強制性的,而是由編譯器決定是否執行。
在Debug中,我用
&v
得到了不同的結果,但是在Release模式下,我得到了相同的結果。
對於編譯器而言,在調試模式下不執行某些優化是非常典型的。
為什么函數返回不移動向量?
該載體在這個意義上移動 v
是移動構造的。 但是看來您通過“移動”還具有其他含義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.