C ++标准专门禁止在常量表达式中调用new
(N4296第5.20节[expr.const]):
条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:
...
- 一个新表达式(5.3.4);
此禁令(据我所见)扩展到{em>所有形式的new
,包括新的展示位置。但是,由于placement new实际上并没有分配任何内存,只是在给定位置运行构造函数,并且因为在constexpr
上下文中获取变量的地址是合法的(事实上,std::addressof
将是在C ++中的constexpr 17),在我看来,这个禁令(原则上至少)可以放宽,以允许在constexpr函数中放置新的。
所以我的问题是,我错过了什么吗?在constexpr
函数中禁止放置new是否有充分的理由?
(对于上下文:当前规则几乎要求启用constexpr的和类型如std::variant
实现为递归联合。能够使用std::aligned_storage
和放置等内容会更好新的,但目前这是不可能的。)
答案 0 :(得分:1)
#include <cstdint>
#include <iostream>
class A {
public:
constexpr A() = default;
int a = 5;
};
constexpr int foo() {
uint8_t space[sizeof(A)];
new(space) A();
A& a = *reinterpret_cast<A*>(space);
return a.a;
}
int main() {
std::cout << foo() << std::endl;
}
编译器可以理解上述程序当然是可以想象的。通常我认为这是不可行的,因为确保放置参数始终指向本地内存所需的复杂性。
我不认为&#34;记忆&#34;的概念甚至适用于constexpr函数,因为它们通常在编译时进行评估。
答案 1 :(得分:1)
placement new与当前的constexpr
世界不能很好地融合在一起,因为它允许使用其底层字节表示(带有值初始化)来构建对象。而且这在标准中没有定义(提醒一下,甚至在constexpr中都没有二补码)
通过查看C ++标准讨论,它可以允许以后查看对象类型表示形式(因为您仍然持有字节数组)
答案 2 :(得分:-1)
没有任何概念上的原因,新的放置无法奏效。我认为这是一个疏忽,放置new基本上只是在预定义的内存位置调用构造函数。
确保placement new参数具有有效的参数位置并不比确保对随机指针的写入有效更难。