gpt4 book ai didi

C++ move aligned_storage数组元素的正确方法

转载 作者:行者123 更新时间:2023-12-03 02:27:22 24 4
gpt4 key购买 nike

正如标题所说,我想知道 move 数组中的元素的正确方法是什么,例如:

std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, N> data;

是不是就这么简单:

data[dst] = data[src];

或者我是否需要添加其他内容,例如 move ,因为它的存储未初始化,我是否需要使用复制或 move 构造函数,例如:

new (&data[dst]) T(std::move(data[src]));

由于 data[src] 不是正确的类型 T,我是否需要这样做:

new (&data[dst]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[src])));

我正在寻找最灵活的方式来 move 任何可能的项目,包括仅 move 类型等。

基本上,我正在创建一个打包数组,它始终将元素 move 到内存中连续的位置,即使为了防止数组的事件部分中出现空洞而删除了元素。

编辑:由于评论想要一个最小的例子,我猜是这样的:

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));
}
};

最佳答案

粗略地说,

std::aligned_storage 本身只是一个字节集合。没有任何东西可以 move ,std::move(data[src])只是一个空操作。您应该首先使用placement new创建一个对象,然后您可以通过在新位置 move 构造该对象来 move 该对象。

简单的例子:

auto ptr = new (&data[0]) T();
new (&data[1]) T(std::move(*ptr));
std::destroy_at(ptr);

in the case of T being something like unique_ptr, or any other similar edge case, there shouldn't be any issue with calling the destroy on the old element index correct?

从对象 move 后,它会处于某种有效状态,并且该对象仍然需要被销毁。

since data[0] is just a collection of bytes, would a pointer to it work, or would that pointer need to be reinterpret cast before being used in the move constructor?

如果用 reinterpret_caststd::launder 装饰它就会起作用,就像您在问题中所写的那样:

new (&data[1]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[0]))));

标准库包含一些用于处理未初始化内存的有用函数。完整列表可以找到here (请参阅未初始化存储部分)。

关于C++ move aligned_storage数组元素的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56525814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com