【发布时间】:2019-06-10 11:49:02
【问题描述】:
正如标题所说,我想知道在数组中移动元素的正确方法是什么:
std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, N> data;
就这么简单吗:
data[dst] = data[src];
或者我是否需要添加其他内容,例如移动,因为它的存储未初始化,我是否需要使用复制或移动构造函数,例如:
new (&data[dst]) T(std::move(data[src]));
由于 data[src] 不是正确的类型 T,我是否需要改为:
new (&data[dst]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[src])));
我正在寻找最灵活的方式来移动任何 T 可能的项目,包括仅移动类型等。
基本上,我正在创建一个压缩数组,它始终将元素移动到内存中连续的位置,即使删除元素以防止数组的活动部分出现漏洞。
编辑: 由于 cmets 想要一个最小的例子,我猜是这样的:
template<class T, std::size_t N>
class SimpleExampleClass {
std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, N> data;
public:
void move_element(std::size_t src, std::size_t dst) {
// data[dst] = data[src]; ?
// or
// new (&data[dst]) T(std::move(data[src]));
// or
// new (&data[dst]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[src])));
// or
// something else?
// then I would need some way to clean up the src element, not sure what would suffice for that.
// as calling a destructor on it could break something that was moved potentially?
}
// Other functions to manipulate the data here... (example below)
template<typename ...Args>
void emplace_push(Args&&... args) noexcept {
new (&data[/*some index*/]) T(std::forward<Args>(args)...);
}
void push(T item) noexcept {
emplace_push(std::move(item));
}
};
【问题讨论】:
-
data[dst]中有什么内容?data[src]中有什么内容?出示您的minimal reproducible example。 -
@Evg 所以我会使用
new (&data[dst]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[src])));之类的东西,对吧? -
提示:使用aligned_storage 时,您需要知道您已经构建了哪些项目(好吧,如果
std::is_pod<T>为假)。所以你以后只能破坏它们。 -
@KamilCuk, BTW,
std::is_pod在 C++20 中已弃用。
标签: c++ move-semantics placement-new