我使用visual studio 2010,其stl实现来自dinkumware
我注意到当向量的内部缓冲区增长时,会调用_Uninitialized_move。这很像std :: uninitialized_copy。
我知道对于非标量类型,逐位应对并不安全,但在这种情况下我感到困惑,因为旧对象很快就会被破坏。看起来所有类型的按位应对是安全的,因此在_Uninitialized_move之后我们只需要免费的原始缓冲区。这将为非平凡的对象节省大量的复制构造函数和析构函数。
那么,只为非标量类型移动内容是否安全?
答案 0 :(得分:4)
如果你完全确定你移动的对象没有彼此的指针(包括那些对象的子对象) - 那么只需移动内容就可以了。但是,除非你知道内部的类型是如何设计的,否则你无法知道。一个例外是,如果类型不大于指针(sizeof(Type) <= sizeof( void* )
),那么它很可能没有指向同一容器中的对象的指针,所以通常它可以被移动。
答案 1 :(得分:4)
在C ++ 11中,有许多特性需要知道是否可以安全地执行位操作。
在您的情况下,我认为您应该使用std::is_trivially_move_constructible<T>
。这些特征是使用编译器内在函数实现的(非便携式,这就是它在标准库中的原因),但它们本身都是可移植的。
因此,代码应类似于:
template <typename T>
void move_to(T* storage, T* begin, T* end) {
if (std::is_trivially_move_constructible<T>::value) {
memmove(storage, begin, (end - begin) * sizeof(T));
} else {
for (; begin != end; ++begin, ++storage) {
new (storage) T(std::move(*begin));
}
}
}
编译器将在编译时优化if
,具体取决于类型是否可以简单地移动构造,并且只留下有趣的分支。
答案 2 :(得分:1)
没有。如果他们有相互指针,那么简单的逐位移动将使这些无效。