Насколько я понимаю, правила о неявном создании объектов с неявным временем жизни применяются только к C++ 20 и новее. Я застрял на C++ 17, поэтому мне было интересно, могу ли я исправить этот пример кода (чтобы он не был UB в C++ 17), добавив новое выражение размещения, которое не инициализирует объект , так:
#include <cstdlib>
#include <new>
struct X { int a, b; };
// I believe writing to the fields of the returned object is UB in C++17, OK in C++20 and later.
X* make_uninitialized_x() {
auto p = (X*)std::malloc(sizeof(X));
return p;
}
// Is writing to the fields of the returned object OK in C++17 and earlier?
X* make_uninitialized_x_fixed_for_cpp17() {
auto p = (X*)std::malloc(sizeof(X));
new (p) X; // This gets optimized away with -O1 flag
return p;
}
Да, до C++20 malloc
не запускал время жизни объекта, а new
запускает.
Интересно, требуется ли std::launder, когда вы возвращаете p
, а не напрямую new (p) X
.
@ Jarod42 Хороший вопрос, может быть. Другой вариант — использовать return new (p) X;
, что, вероятно, также должно решить эту потенциальную проблему.
Отвечая на мой собственный вопрос: согласно комментариям, любая из приведенных ниже фиксированных функций будет в порядке в С++ 17 и более ранних версиях.
#include <cstdlib>
#include <new>
struct X { int a, b; };
X* make_uninitialized_x_fixed_v1() {
auto p = (X*)std::malloc(sizeof(X));
new (p) X;
return std::launder(p);
}
X* make_uninitialized_x_fixed_v2() {
auto p = (X*)std::malloc(sizeof(X));
return new (p) X;
}
Да, новое размещение — это способ создать объект в месте хранения.