放置新的移动构造函数与愚蠢的移动赋值small_vector
Placement new with move constructor vs move assignment in folly small_vector
在研究类似 constexpr 向量的容器的想法时,我 运行 进入了 folly's small_vector container。我正在通读实现,并对 moveObjectsRightAndCreate
:
的这一部分感到困惑
for (; in != first && out > lastConstructed;) {
// Out must be decremented before an exception can be thrown so that
// the rollback guard knows where to start.
--out;
new (out) T(std::move(*(--in)));
}
for (; in != first;) {
--out;
*out = std::move(*(--in));
}
for (; out > lastConstructed;) {
--out;
new (out) T(create());
}
for (; out != first;) {
--out;
*out = create();
}
我的理解是:对于数组中内存未初始化的部分,他们使用placement new with std::move
。对于先前移动对象的数组部分,他们使用移动赋值。
主要区别似乎是使用移动构造函数还是移动赋值,但我不确定我是否理解这些选择的含义。为什么不对这两种情况都使用 placement new 呢?为什么不对这两种情况都使用移动分配?因为我们知道数组的大小,所以我们永远不会在未初始化的内存上调用析构函数,对吗?
Why not use placement new for both cases
可能是因为这不允许他们指定不会通过插入调用元素的析构函数(以防容量不增长)。他们似乎没有准确地指定他们的 API,但他们可能认为这是隐含的预期。
或者他们可能假设或期望赋值在理论上对于某些类型比销毁 + 构造更有效。
究竟是其中之一,还是其他原因,只能由容器的作者来回答。
Why not use move assignment for both cases?
因为非平凡类型在未初始化内存上的移动赋值行为未定义。
在研究类似 constexpr 向量的容器的想法时,我 运行 进入了 folly's small_vector container。我正在通读实现,并对 moveObjectsRightAndCreate
:
for (; in != first && out > lastConstructed;) {
// Out must be decremented before an exception can be thrown so that
// the rollback guard knows where to start.
--out;
new (out) T(std::move(*(--in)));
}
for (; in != first;) {
--out;
*out = std::move(*(--in));
}
for (; out > lastConstructed;) {
--out;
new (out) T(create());
}
for (; out != first;) {
--out;
*out = create();
}
我的理解是:对于数组中内存未初始化的部分,他们使用placement new with std::move
。对于先前移动对象的数组部分,他们使用移动赋值。
主要区别似乎是使用移动构造函数还是移动赋值,但我不确定我是否理解这些选择的含义。为什么不对这两种情况都使用 placement new 呢?为什么不对这两种情况都使用移动分配?因为我们知道数组的大小,所以我们永远不会在未初始化的内存上调用析构函数,对吗?
Why not use placement new for both cases
可能是因为这不允许他们指定不会通过插入调用元素的析构函数(以防容量不增长)。他们似乎没有准确地指定他们的 API,但他们可能认为这是隐含的预期。
或者他们可能假设或期望赋值在理论上对于某些类型比销毁 + 构造更有效。
究竟是其中之一,还是其他原因,只能由容器的作者来回答。
Why not use move assignment for both cases?
因为非平凡类型在未初始化内存上的移动赋值行为未定义。