我有类似以下内容
class Base {
public:
explicit Base(int* i) noexcept { type = new int; *type = *i; };
constexpr Base(std::nullptr_t) : type(nullptr) { };
~Base() { cout << "Destroying!" << endl; delete type; };
protected:
int* type;
};
class Derived : public Base {
public:
explicit Derived(int* i) noexcept : Base(i) { };
//constexpr Derived(std::nullptr_t) : type(nullptr) { };
//constexpr Derived(std::nullptr_t) : Base(nullptr) { };
~Derived() { };
};
我想为派生类实现一些 constexpr
null 构造函数,但编译器对这两个选项和我所做的类似测试提示很多。
当然,代码更复杂,我有一个不透明的处理程序,析构函数应该以更复杂的方式运行。资源释放始终相同(不需要多个析构函数,只需 Base
一个)。
我不知道如何实现这一点,也许我走错了路?有任何想法吗?我希望能够做这样的事情:
Derived a(nullptr);
Derived b(handler1);
Base c (nullptr);
Base d (handler2);
并且,在清理过程中,handler1
和 handler2
都以某种方式进行管理。
编辑:
Clang(版本 3.4)提示:
error: constexpr constructor never produces a constant expression [-Winvalid-constexpr]
并且 gcc(版本 4.8 [编辑:多个版本,尚未检查全部])在使用时不会提示
constexpr Derived(std::nullptr_t) : Base(nullptr) { };
事实上,gcc
似乎做了我想要实现的目标,但我对constexpr的理解不够深入,无法知道哪个编译器做得正确以及我如何修改问题所在。
最佳答案
常量表达式的类型必须是文字类型。事实上,“文字类型”分类单元的全部目的是“成为可以作为常量表达式的东西”。请参阅[expr.const]:
A conditional-expression
e
is a core constant expression unless the evaluation ofe
, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:...
— an invocation of a function other than a constexpr constructor for a literal class, a constexpr function,
...
因此,constexpr
构造函数只允许您在文字类上生成常量表达式,否则,正如编译器告诉您的那样,它将“永远不会生成常量表达式”。
文字类以这种方式受到 [basic.types] 的约束:
A type is a literal type if it is:
...
— a class type (Clause 9) that has all of the following properties:
- it has a trivial destructor,
- it is an aggregate type (8.5.1) or has at least one
constexpr
constructor or constructor template that is not a copy or move constructor, and- all of its non-static data members and base classes are of non-volatile literal types.
但是,从 C++14 开始(特别是从 N3652 开始),constexpr
构造函数有另一种不相关的用途:它们允许静态初始化(在 [basic.start.初始化]):
A constant initializer for an object
o
is an expression that is a constant expression, except that it may also invokeconstexpr
constructors foro
and its subobjects even if those objects are of non-literal class types [Note: such a class may have a non-trivial destructor — end note].
回顾一下:从 C++14 开始,constexpr
有两个用途:
C++11 解释:“常量表达式”是与其值相同的表达式(即,其计算没有副作用); constexpr 变量只是其值的占位符,并不用于其对象标识,并且通常期望常量表达式可以自由地替换为其(编译时已知的)值。 p>
C++14
constexpr
函数,包括构造函数:这些函数(包括构造函数)可以在静态初始化阶段调用,以对具有静态存储持续时间的变量进行常量初始化。如果变量是对象,它们仍然保留其对象标识,并且可能需要动态销毁,但它们的初始化发生在任何动态初始化之前,并且不受排序的影响。
关于c++ - constexpr 用于派生类中空初始化的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27167958/