簡體   English   中英

從函數返回std :: vector是淺表副本嗎?

[英]Will returning std::vector from a function be a shallow copy?

假設我有兩個功能。 一個返回std::vector<int> ,另一個返回具有std::vector<int>成員的類。

// using only the vector
std::vector<int> buildVector(){
     std::vector<int> value;
     // build the vector...
     return value;
};

// using and returning a class instead
struct Something{
    std::vector<int> m_vector;
}
Something buildSomething(){
     Something value;
     // build the object...
     return value;
};

這兩個函數buildVector()buildSomething()執行它們返回的對象的淺表副本(避免不必要的堆分配)? 還是不會? 還是他們的行為有所不同?

我假設向量的內部指針將保持有效,除非我弄錯了,並且局部變量決定取消分配此內存。 (他們會嗎?)

我本身並不追求性能,但是我不想執行不需要的分配。 以這種形式編寫函數對於我正在做的事情來說是最自然的。

我的編譯器不使用C ++ 11。 與先前的標准相比,當前標准是否會出現不同的情況?

簡短的答案:在C ++ 11之前,它將復制每個元素。 它將在一側分配一個緩沖區並執行memcpy等操作。 由於向量存儲連續內存,因此非常快,非常有效。 指向由值返回的堆棧向量的指針可能不再有效。

在C ++ 11中,Std lib伙計們可以使用move操作將一個矢量中的內臟有效地“竊取”到另一個矢量中,從而導致兩次指針交換。 這是特定於實現的,因此盡管您的編譯器可能是C ++ 11,但Stdlib可能不是最新的。 C ++ 14使此操作更加透明和令人敬畏,但同樣,您的Stdlib平台實現可能無法更新以利用Move語義。

作為附帶說明,“三個規則”已成為“五個規則”。 看到三規則成為C ++ 11的五規則嗎?

我希望找出語言人士是否可以對此做些...某種編譯器魔術,使其再次成為三個規則,以防止代碼膨脹。

首先:在所有情況下, buildVectorbuildSomething在復制/移動或任何數據方面都是完全等效的(除非您的編譯器有一個腦筋急轉的優化器)。

在C ++ 11之前,您只能依靠編譯器。 該代碼的語義是“分配value所需的內存,為return值分配新的內存,然后將數據復制到該內存中,並且(如果發生)將返回值復制到調用代碼中的變量中(同樣,分配新的內存並復制每個元素)”。 這似乎很糟糕,但是可能會忽略兩個副本中的一個或兩個副本,因此(大多數(或也許是全部))生產質量的編譯器,代碼更有可能以“分配value所需的內存……並突然使在調用代碼的變量是完全一樣的對象作為value “(無(C ++可見)拷貝,移動,或任何任何需要)。

在C ++ 11中,任何可能發生“復制省略”的地方,都必須將move構造函數作為后備調用(出於兼容性考慮,如果沒有可用的move構造函數,則進一步回退到copy構造函數)。 std::vector的move構造函數(在符合C ++ 11的實現中)的工作方式是從其操作數中“竊取”內存,並創建一個新的std::vector ,其值與要從其移出的值相同,並與移出的值相同來自vector的有效但未指定狀態。 move操作不涉及內存分配或數據復制,而僅涉及固定數量的指針復制。

暫無
暫無

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

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