在键入的 std::array 中放置新的和 std::destroy_at 是否安全?
Safety of placement new and std::destroy_at in typed std::array?
考虑以下示例:
#include <array>
#include <memory>
class trivial
{
public:
trivial() = default;
trivial(int a, float b) : m_a(a), m_b(b) {}
private:
int m_a;
float m_b;
};
template<typename T>
void write(T& arr, size_t idx, int a, float b)
{
::new(static_cast<void*>(std::addressof(arr[idx]))) trivial(a, b);
}
template<typename T>
void destroy(T& arr, size_t idx)
{
std::destroy_at(std::addressof(arr[idx]));
}
int main()
{
auto arr = std::array<trivial, 20>();
write(arr, 3, 10, 20.0f);
destroy(arr, 3);
}
对任意(但合理的)数据数组使用放置 new
和 std::destroy_at
就地安全吗?这里是否存在任何风险或潜在的未定义行为,或可移植性问题?假设我们不会尝试分配给已销毁的值,据我所知这是未定义的。
我注意到这种方法比使用 std::aligned_storage
和 reinterpret_cast
的基准测试效果更好,这主要是因为 std::launder
作为优化障碍。如果我对将我的值存储在 std::array
中的额外限制感到满意(例如需要默认构造函数),这是一个可接受的用例吗?
你对 std::array arr
的第三个元素进行了双重破坏。一次是显式销毁(destroy
调用),一次是隐式销毁(当 arr
超出范围时)。根据 C++ 标准,这会导致未定义的行为。
15.4 Destructors [class.dtor]
...
16 Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended. [ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined. —end example ]
以上引用中的示例与您尝试做的有点相似。
考虑以下示例:
#include <array>
#include <memory>
class trivial
{
public:
trivial() = default;
trivial(int a, float b) : m_a(a), m_b(b) {}
private:
int m_a;
float m_b;
};
template<typename T>
void write(T& arr, size_t idx, int a, float b)
{
::new(static_cast<void*>(std::addressof(arr[idx]))) trivial(a, b);
}
template<typename T>
void destroy(T& arr, size_t idx)
{
std::destroy_at(std::addressof(arr[idx]));
}
int main()
{
auto arr = std::array<trivial, 20>();
write(arr, 3, 10, 20.0f);
destroy(arr, 3);
}
对任意(但合理的)数据数组使用放置 new
和 std::destroy_at
就地安全吗?这里是否存在任何风险或潜在的未定义行为,或可移植性问题?假设我们不会尝试分配给已销毁的值,据我所知这是未定义的。
我注意到这种方法比使用 std::aligned_storage
和 reinterpret_cast
的基准测试效果更好,这主要是因为 std::launder
作为优化障碍。如果我对将我的值存储在 std::array
中的额外限制感到满意(例如需要默认构造函数),这是一个可接受的用例吗?
你对 std::array arr
的第三个元素进行了双重破坏。一次是显式销毁(destroy
调用),一次是隐式销毁(当 arr
超出范围时)。根据 C++ 标准,这会导致未定义的行为。
15.4 Destructors [class.dtor]
...
16 Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended. [ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined. —end example ]
以上引用中的示例与您尝试做的有点相似。