在 C++17 中使用 placement-new 使用简单的默认构造函数显式创建对象

Explicit creation of objects with a trivial default constructor using placement-new in C++17

提问人:StableGeneous 提问时间:2/15/2023 更新时间:2/17/2023 访问量:68

问:

我的理解是,关于隐式创建隐式生存期对象的规则仅适用于 C++20 及更高版本。我被 C++ 17 困住了,所以我想知道我是否可以通过添加一个不初始化对象的放置新表达式来修复这个示例代码(这样它就不是 C++17 中的 UB),如下所示:

#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++ C++17 malloc placement-新

评论

5赞 NathanOliver 2/15/2023
是的,放置新是在存储位置创建对象的方法。
1赞 Ternvein 2/15/2023
是的,直到 C++20 没有开始对象的生命周期,但确实如此。mallocnew
3赞 Jarod42 2/15/2023
我想知道是否需要 std::launder,因为您返回而不是直接返回.pnew (p) X
4赞 NathanOliver 2/15/2023
@Jarod42 好点,可能是。另一种选择是使用它可能也可以解决该潜在问题。return new (p) X;

答:

2赞 StableGeneous 2/17/2023 #1

回答我自己的问题:根据评论,下面的任何一个固定函数在 C++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;
}