Почему gcc не использует memmove в std :: uninitialized_copy?

std::uninitialized_copy копирует в неинициализированный диапазон памяти. Это можно сделать с помощьюmemmove для побитовых копируемых типов. Я прошел через пример кода в GDB (компиляция с GCC 5.2.0). Тем самым я заметил, чтоmemmove не используется вообще.

В примере__is_trivial(Bar) используется для определенияmemmove может быть использовано. (Правильно) оцениваетfalse какBar имеет нетривиальный конструктор по умолчанию (см. вызовstd::__uninitialized_copy<false>::__uninit_copy(...) вbits/stl_uninitialized.h линия123и далее). Но почему__is_trivial даже имеет отношение кstd::uninitialized_copy? В соответствии сБьярне std::is_trivially_copyable должно быть достаточно. Обратите внимание, что последний оцениваетtrue в примере, т.е.memmove оптимизацияприменимо.

Я знаю, что стандарт не требует какой-либо конкретной реализации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 тривиально (ср.__is_trivial(Bar)),uninitialized_copy так быстро, какmemmoveесли нет,uninitialized_copy так же быстро, как нашfor петля. В общем и целомmemmove был только значительно быстрее (2x) на маленькомBarс (т.е. изменитьint v; вchar v;). В остальном производительность была практически одинаковой.

редактировать: Правильные ссылки наstd::is_trivially_..., Точное название государства.

Ответы на вопрос(1)

Ваш ответ на вопрос