std::flush、std::vector和move只能构造类型



对于我的一个项目的功能请求,我认为/有人建议我使用std::launder在一个向量中移动元素,其中元素仅可移动构造(没有定义移动赋值运算符)
目标是将最后一个元素移动到给定的位置i,然后弹出前一个元素。

换句话说,生成的代码将是这样的(目的是简化版本):

void foo(std::vector<my_type> &vec, std::size_t i) {
my_type *el = vec.data() + i;
el->~my_type();
new (std::launder(el)) my_type{std::move(vec.back())};
vec.pop_back();
}

其中my_type定义为:

struct my_type { const int v; };

使用std::launder的目的是针对可能的优化设置障碍,因为my_type中的vconst。因此,能够回收为vec[i]保留的内存,以便用不同的实例替换包含的对象(实际上,理论上我正在最后一项移动到不同的位置)。

这是一个有效的方法/解决方案吗?还是仍然是UB,因为如果我做了类似的事情而不重复std::launder,就会发生这种情况?

据我所知,std::launder的目的是允许用户做这样的事情,因此在我看来,上面的片段是合法的。但如果我错了,我不会感到惊讶,所以我想有一个比我更有经验的的反馈

---编辑

类似地,我也想交换到相同类型的元素
生成的代码应该是这样的:

const auto tmp = std::move(vec[i]);
vec[i].~object_type();
new (std::launder(&vec[i])) object_type{std::move(vec[j])};
vec[j].~object_type();
new (std::launder(&vec[j])) object_type{std::move(tmp)};

我很有信心,如果std::launder符合第一个例子,那么出于类似的原因,这个例子应该也能工作。我错了吗?

launder为您获取一个指向已存在对象的指针。

那里没有物体。你刚刚在前一行破坏了它。

即使是对launder本身的调用也是纯纯UB。

对于这种情况,当访问新创建的对象时,需要launder。当你创建它时不会。

最新更新