c++ - constexpr 用于派生类中空初始化的构造函数

标签 c++ c++11

我有类似以下内容

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

并且,在清理过程中,handler1handler2 都以某种方式进行管理。

编辑:

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 of e, 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 invoke constexpr constructors for o 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 有两个用途:

  1. C++11 解释:“常量表达式”是与其值相同的表达式(即,其计算没有副作用); constexpr 变量只是其值的占位符,并不用于其对象标识,并且通常期望常量表达式可以自由地替换为其(编译时已知的)值。 p>

  2. C++14 constexpr 函数,包括构造函数:这些函数(包括构造函数)可以在静态初始化阶段调用,以对具有静态存储持续时间的变量进行常量初始化。如果变量是对象,它们仍然保留其对象标识,并且可能需要动态销毁,但它们的初始化发生在任何动态初始化之前,并且不受排序的影响。

关于c++ - constexpr 用于派生类中空初始化的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27167958/

相关文章:

java模板泛型类型

c++11 - 无法按值捕获随机引擎

c++ - 我能以某种方式不写出完整的限定返回类型名称吗?

c++ - 在 DirectX 中创建和使用纹理

c++ - 了解提案 N3650 for C++1y 中有关可恢复函数的示例

c++ - 如何强制编译器在 C/C++ 本身中声明函数?

c++ - 如何启用 VS2013 c++ 编译器功能?

c++ - unordered_set 与 vector 的迭代速度

C++11 std::forward 一个指针

c++ - 在 C++ 中使用 getter、setter