为什么gcc在std :: uninitialized_copy中没有使用memmove?

时间:2015-11-02 16:42:34

标签: c++ c++11 gcc stl

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 ff中的123调用。 但为什么__is_trivial甚至与std::uninitialized_copy相关? 根据{{​​3}} Bjarne应该足够了。请注意,后者在示例中评估为true,即。 memmove优化std::is_trivially_copyable

我知道,该标准不需要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

更新:我们进行了一些测试,比较memmoveuninitialized_copy和简单for循环的实际运行时间。如果Bar是微不足道的(参见__is_trivial(Bar)),则uninitialized_copymemmove一样快,如果不是,uninitialized_copyfor一样快循环。总体memmove2x小{{更改Barint v;}上的速度明显加快(char v;)。否则表现基本相同。

修改:更正std::is_trivially_...的引用。更确切地说是州名。

1 个答案:

答案 0 :(得分:0)

对于未来的读者:这已作为gcc增强here提交。

相关问题