Рассмотрим следующий пример:
#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
(например, требуется конструктор по умолчанию), это приемлемый вариант использования?