当前位置: 首页 > 知识库问答 >
问题:

constexpr函数中的New和delete

姜博
2023-03-14

假设我们有课

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

    int& x_;
};

在带有g++-10-std=c++20的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);
}

让我们尝试将运算符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;
}

但是现在有两个错误:我们的内存分配new和放置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*)’

因此,让我们尝试解决这些错误。使用 我们可以得到如下代码:

constexpr int do_foo_3() {
    std::allocator<Foo> alc;
    int x = 0;
    Foo* p = alc.allocate(1);
    p = std::construct_at(p, x);
    std::destroy_at(p);
    alc.deallocate(p, 1);
    return x;
}

int main() {
    static_assert(do_foo_3() == 2);
}

问题

我的用法和标准库中这些操作符的用法有什么区别?在std::construct_atstd::allocator ::allocal 中不是也发生了同样的事情吗?

备注

我试图通过简单地从 复制它的实现来复制std::construct_at,但我得到了同样的错误:

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*)

共有1个答案

耿珂
2023-03-14

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

您的用法不称为std::allocator ::allocal std::construct_at

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

为了确定表达式E是否是核心常量表达式,对[allocator.members]中定义的std::allocator 的成员函数的调用的求值(其中t是文字类型)不会取消E作为核心常量表达式的资格,即使这样的调用的实际求值否则将无法满足对核心常量表达式的要求。类似地,对std::destroy_atstd::ranges::destroy_atstd::construct_at或std::ranges::construct_at的调用的求值不会取消E作为核心常量表达式的资格,除非:[...]

对于普通的new表达式,在常数求值期间,它从不调用::operator new:

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

 类似资料:
  • 我使用MSVC v141和< code>/std:c 17进行编译。 编译得很好,而 失败原因: 错误C2131:表达式未计算为常量 失败是由在其生命周期之外读取变量引起的 注意:请参阅“FOO”的用法 这是正确的行为还是 MSVC 中的错误?

  • 本文向大家介绍C++中的const和constexpr详解,包括了C++中的const和constexpr详解的使用技巧和注意事项,需要的朋友参考一下 C++中的const可用于修饰变量、函数,且在不同的地方有着不同的含义,现总结如下。 const的语义 C++中的const的目的是通过编译器来保证对象的常量性,强制编译器将所有可能违背const对象的常量性的操作都视为error。 对象的常量性可

  • 我正在尝试编译以下C代码(另存为example4.cpp) 此代码给出以下错误: example4.cpp:在函数'Conconexpr double nth(double, int)':example4.cpp:24: 9: error:调用非Conconexpr函数'std::basic_ostream 谁能推荐一下吗? 谢谢你。

  • 我试图在C类中实现一个返回模板参数的constexpr成员函数。代码应该是c 11兼容的。然而,当模板化的类还包含STL容器作为数据成员时,比如STD::vector(const expr成员函数不涉及它),我会遇到编译问题。 以下代码给出了一个最小的示例: 代码使用命令正确编译 g -std=c 14 -O3 快速测试.cpp -o 测试 -Wall clang-STD = c 11-O3 qu

  • 为什么 C 编译器可以将函数声明为 constexpr,而 constexpr 不能是 constexpr? 例如:http://melpon.org/wandbox/permlink/AGwniRNRbfmXfj8r 输出: 为什么此行出错:

  • 由于声明为constexpr的函数有可能在运行时调用,编译器根据哪些条件决定是在编译时还是在运行时计算它? 在这种情况下,i在编译时是未知的,这可能是编译器将POW()视为在运行时调用的常规函数的原因。然而,这种动态,尽管看起来很方便,却有一些不切实际的含义。例如,会不会有这样一种情况,我希望编译器在编译时计算一个常数表达式函数,而编译器决定将其视为正常函数,而它在编译时也可以工作?有什么已知的常