在 constexpr 函数中放置 new 和 delete

She*_*rei 5 c++ c++20

假设我们有一些课程

struct Foo {
    constexpr Foo(int& x) : x_(x) { x_++; }
    constexpr ~Foo() noexcept     { x_++; }

    int& x_;
};
Run Code Online (Sandbox Code Playgroud)

在 C++20 中,g++-10 -std=c++20我们可以有这样的函数:

constexpr int do_foo_1() {
    int x = 0;
    Foo* p = new Foo(x);
    delete p;
    return x;
}

int main() {
    static_assert(do_foo_1() == 2);
}
Run Code Online (Sandbox Code Playgroud)

让我们尝试将运算符new分为内存分配和就地构造。所以新函数看起来像这样:

constexpr int do_foo_2() {
    int x = 0;
    Foo* p = static_cast<Foo*>(::operator new(sizeof(Foo)));
    p = ::new ((void*) p) Foo(x);
    p->~Foo();
    ::operator delete(p);
    return x;
}
Run Code Online (Sandbox Code Playgroud)

但是现在有两个错误:我们的内存分配new和placement new不是constexpr!

error: call to non-‘constexpr’ function ‘void* operator new(std::size_t)’
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t, void*)’
Run Code Online (Sandbox Code Playgroud)

因此,让我们尝试解决这些错误。随着<memory>我们能有这样的代码:

error: call to non-‘constexpr’ function ‘void* operator new(std::size_t)’
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t, void*)’
Run Code Online (Sandbox Code Playgroud)

我的用法和标准库中这些运算符的用法有什么区别?引擎盖内std::construct_atstd::allocator<Foo>::allocate引擎盖下不是发生同样的事情吗?

笔记

我试图通过简单地复制它的实现来复制 std::construct_at<stl_construct.h>但我得到了同样的错误:

error: ‘constexpr decltype (...) my_construct_at(_Tp*, _Args&& ...) [...]’ called in a constant expression
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t, void*)
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 7

我的用法和标准库中这些运算符的用法有什么区别?

您的用法未调用std::allocator<T>::allocatestd::construct_at

这些特定功能 - 以及其他一些功能 - 被特别授予正常规则的例外情况

为了确定表达式E是否是核心常量表达式,对std?::?allocator<T>[allocator.members] 中定义的成员函数的调用的评估 ,其中T是文字类型,不会取消E作为核心常量表达式的资格,即使对此类调用的实际评估将无法满足核心常量表达式的要求。类似地,为一个呼叫的评价std?::?destroy_­atstd?::?ranges?::?destroy_­atstd?::?construct_­at,或std ::范围:: construct_at不资格????Ë从一个核心常量表达式除非:[...]

至于普通new表达式,在不断评估期间,它从不调用::operator new

在常量表达式的求值过程中,总是省略对分配函数的调用。

  • 这是否意味着我永远(在 c++20 中)无法制作自己的 constexpr 分配器? (3认同)