std::uninitialized_copy
複製到未初始化的內存範圍內。 這可以使用memmove
來完成按位可複製類型。 我在gdb中使用下面的示例代碼(用gcc 5.2.0編譯)。因此我觀察到memmove
根本沒有使用。爲什麼gcc在std :: uninitialized_copy中使用memmove?
在該示例中,用於確定是否可以使用memmove
。 它(正確地)評估爲false
爲Bar
有一個非平凡的默認構造函數(參見調用std::__uninitialized_copy<false>::__uninit_copy(...)
bits/stl_uninitialized.h
行123
ff)。 但爲什麼__is_trivial
甚至與std::uninitialized_copy
有關? 根據Bjarnestd::is_trivially_copyable
應該足夠了。請注意,後者在該示例中評估爲true
,即。 memmove
優化is applicable。
我知道,該標準不需要任何具體的實現std::uninitialized_copy
。我只是想知道爲什麼__is_trivial
更受青睞,即使std::is_trivially_copyable
作爲適用於gcc實現的替代方案而存在?
示例代碼:
#include <iostream>
#include <memory>
#include <vector>
#include <type_traits>
struct Bar
{
Bar() : v(42) {};
Bar(Bar const &) = default;
Bar(Bar &&) = default;
Bar & operator=(Bar &&) = default;
Bar & operator=(Bar const &) = default;
~Bar() = default;
int v;
};
int main() {
std::cout
<< std::is_trivially_move_constructible<Bar>::value
<< " " << std::is_trivially_copy_constructible<Bar>::value
<< " " << std::is_trivially_copyable<Bar>::value
<< " " << std::is_trivial<Bar>::value
<< " " << __is_trivial(Bar) << std::endl;
size_t const num_elements = 1 << 27;
std::vector<Bar> v(num_elements);
Bar * vc = (Bar *) std::malloc(num_elements * sizeof(Bar));
std::uninitialized_copy(v.begin(), v.end(), vc);
std::free(vc);
}
輸出示例:1 1 1 0 0
更新:我們做了一些測試,比較的memmove
,uninitialized_copy
實際運行時和一個簡單的for
循環。如果Bar
是微不足道的(參見),uninitialized_copy
與memmove
一樣快,如果不是,uninitialized_copy
與我們的for
循環一樣快。總體上memmove
僅在小Bar
s(即,將int v;
更改爲char v;
)上顯着更快(2x
)。否則,表現基本相同。
編輯:正確引用std::is_trivially_...
。更準確地說明州名稱。
你正在混淆'is_trivially_copy_constructible'和'is_trivially_copyable'。 Bjarne的示例代碼使用第二個,而不是第一個。 – pmr
這是真的,我糾正了這個問題。雖然'is_trivially_copyable'也評估爲'true',但問題仍然存在。 – m8mble
您複製到未初始化的內存範圍。我解釋它的方式,不能有重疊(因爲一個是初始化的,另一個不是),所以你可以使用'memcpy'而不是'memmove'。 –