在 C++ 中减少 `constexpr` 对象生命周期合法吗?
Is reduction of `constexpr` object lifetime legal in C++?
对于普通对象(即使是 const
个),允许通过显式调用析构函数来结束它们的生命周期。稍后,例如,程序可以使用放置 new
.
在同一内存位置开始另一个对象生命周期
但是调用constexpr
对象的析构函数合法吗?它能产生一些有用的或至少是格式正确的程序吗?
很容易想象相反的情况:
struct A{
int v = 0;
constexpr void foo() { v ? throw 1 : ++v; }
constexpr ~A() { foo(); }
};
constexpr A y;
int main() { y.~A(); y.~A(); }
这个(很可能是错误格式的)程序被所有编译器接受而没有任何警告:https://gcc.godbolt.org/z/aqMbfjxKT
在 Clang 中,它通过从 A
.
的 constexpr
析构函数中抛出异常来完成
[dcl.constexpr] A constexpr
specifier used in an object declaration declares the object as const.
你可以用这样的对象做任何你能用任何其他 const 对象做的事情。 constexpr
,除了暗示声明对象的常量性之外,似乎不影响对象本身的任何内容。它只影响程序的静态属性,即哪些表达式是常量表达式,哪些模板实例化是有效的等。对于使用 constexpr
声明的对象的 运行 时间行为没有特殊规定说明符。
该标准多次使用类似于“constexpr 对象”的短语,但它似乎用词不当。在我看来,它应该引用 constexpr 变量。不应该有“constexpr 对象”这样的东西(就像没有内联对象),只有 constexpr 变量(就像有内联变量)。毕竟,constexpr
是一个 decl-specifier,就像 inline
。这些变量所指的对象只是const.
对于普通对象(即使是 const
个),允许通过显式调用析构函数来结束它们的生命周期。稍后,例如,程序可以使用放置 new
.
但是调用constexpr
对象的析构函数合法吗?它能产生一些有用的或至少是格式正确的程序吗?
很容易想象相反的情况:
struct A{
int v = 0;
constexpr void foo() { v ? throw 1 : ++v; }
constexpr ~A() { foo(); }
};
constexpr A y;
int main() { y.~A(); y.~A(); }
这个(很可能是错误格式的)程序被所有编译器接受而没有任何警告:https://gcc.godbolt.org/z/aqMbfjxKT
在 Clang 中,它通过从 A
.
constexpr
析构函数中抛出异常来完成
[dcl.constexpr] A
constexpr
specifier used in an object declaration declares the object as const.
你可以用这样的对象做任何你能用任何其他 const 对象做的事情。 constexpr
,除了暗示声明对象的常量性之外,似乎不影响对象本身的任何内容。它只影响程序的静态属性,即哪些表达式是常量表达式,哪些模板实例化是有效的等。对于使用 constexpr
声明的对象的 运行 时间行为没有特殊规定说明符。
该标准多次使用类似于“constexpr 对象”的短语,但它似乎用词不当。在我看来,它应该引用 constexpr 变量。不应该有“constexpr 对象”这样的东西(就像没有内联对象),只有 constexpr 变量(就像有内联变量)。毕竟,constexpr
是一个 decl-specifier,就像 inline
。这些变量所指的对象只是const.