2017-03-10 60 views
3

鑑於std::copy(爲了微不足道的類型顯然)只能實現一個包裝周圍memmove(*),我想知道:類型安全的memcpy C++包裝?

  • 是否有你需要memcpy的次標準C++類型安全的包裝? (我無法計算我忘記乘以sizeof的次數。)
  • 如果標準中沒有任何內容,是否有任何建議?如果不是,爲什麼不呢?
  • 提供自動執行sizeof乘法的memcpy包裝是否存在任何特定障礙?

(*):C++標準庫的實現(從後MSVC 2005()到現代MSVC2015,的libC++等!)衰變std::copy TriviallyCopyable類型memmove。 Bot 不是memcpy。這是因爲:

  • std::copy(src_first, src_last, destination_first)定義:

    行爲是不確定如果d_first在該範圍內[first, last)

    • 只有開始在目標範圍內的時,必須在目標範圍內。目標範圍允許擴展到目標範圍。也就是說,d_first可以在源範圍的「左邊」,目標範圍可以擴展到源範圍。
  • 對於std::memcpy的定義是

    如果對象重疊,則操作是未定義的。

    • 也就是說,全範圍不能重疊:這是允許的memcpy是最快的變種,因爲它可以只是假設源和目的地的記憶是完全脫離。
  • 對於std::memmove,該定義是:

    對象可以重疊:複製發生如同字符被複制到一個臨時的字符數組,然後字符被從陣列複製到dest 。

    • 即,源和目的地範圍可以任意地重疊,沒有任何限制。

鑑於此,很顯然,你可以使用std::memove實現std::copy爲TrivialllyCopyable類型,因爲的memmove不會強加任何限制,並派遣到正確的實現可以通過在類型編譯時完成特點 -

但很難在memcpy方面實現std::copy因爲(a)檢查指針範圍是否重疊將不得不在運行時做,和(b)甚至實現了不相關的運行時檢查內存範圍could be quite a mess

因此,這給我們留下了

void* memcpy(void* dest, const void* src, std::size_t count); 

功能與比恆星界面,在這裏你需要不斷繁殖的非字符對象的輸入計數與他們sizeof,這是完全無類型。

但是memcpy是最快的(並且有很大的差距,你自己去衡量一下),並且當你需要TriviallyCopyable類型的快速拷貝時,你可以到達memcpy。這表面上應該很容易像一個類型安全的包裝來包裝:

template<typename T> 
T* trivial_copy(T* dest, T* src, std::size_t n) { 
    return static_cast<T*>(std::memcpy(dest, src, sizeof(T) * n)); 
} 

但後來,目前還不清楚無論您應該做的通過std::is_trival編譯時檢查或諸如此類,當然可能會有一些討論是否去與確切的memcpy簽名訂單,yadda yadda。

那麼我真的不得不重新發明這個輪子嗎?是否針對標準進行了討論?等


+1

是什麼讓你'std :: copy'必須由'memmove'實現? – nwp

+3

這種包裝的用例是什麼?爲什麼你不喜歡'std :: copy'本身? – Mikhail

+0

你可能舉一個例子,你需要手動memcpy(甚至複製)嗎?在幾乎所有情況下,所有這些都是在後臺使用複製構造函數和副本分配完成的。 – luc

回答

1

爲了澄清mencpy和memove之間的差,根據該docs 的memmove可以位於存儲器複製到重疊源存儲​​器,用於memcpy的,這是不確定的行爲的位置。

對象可以重疊:複製發生如同字符被複制到一個臨時的字符數組,然後字符被從陣列複製到dest。」

是否有一個標準C++類型安全包裝器,用於您需要memcpy的時間? (我不能指望我忘了用的sizeof相乘的次數。)

是,性病::複製(也許,下面解釋)

如果沒有什麼標準,有有什麼建議呢?如果不是,爲什麼不呢?

據我所知,該標準沒有強制使用memmove/memcpy for std :: copy for trivial types。所以這是實施。例如,在visual studio update 2015 update 2 they did use memmove to speed things up

增加STD矢量重新分配和std ::拷貝()的::速度;它們是高達9倍更快,因爲它們調用的memmove(),用於能夠複製平凡類型(包括用戶定義的類型)。

是否有提供的memcpy包裝,自動執行的sizeof相乘任何特定的障礙是什麼?

不,其實你可以通過使用std::is_trivial

編輯自己實現:

根據this document節25.3.1沒有限制到std ::複製只執行復雜:

複雜性:正好是最後的 - 第一個任務。

這非常有意義當你考慮到的memcpy使用的CPU speciffic指令(即並非適用於所有CPU),加快內存拷貝。

+0

請參閱編輯到Q.我現在做了一些背景。 –

+0

@Martin Ba添加了一個編輯,並且請遵循這一點,因爲我今天將在棧代碼審查中發佈替代實現。 – Raxvan

+0

fwiw,甚至MSVC 2005也對'std :: copy'進行了memmove優化(我認爲它們在2005年使用'memmove_s',在2015年使用'memmove',所以2015版本確實進行了優化。) –