空的析构函数vs文字析构函数

时间:2013-01-10 10:19:09

标签: c++ c++11 destructor constexpr user-defined-literals

请考虑以下代码:

#include <iostream>

class Test
{
    public:
        constexpr Test(const int x) : _x(x) {}
        constexpr int get() const {return _x;}
        ~Test() {} // HERE
    protected:
        const int _x;
};

int main()
{
    static constexpr Test test(5);
    return 0;
}

如果删除行HERE,代码编译得很好,但是如果我定义了一个空的析构函数,则会导致编译错误,指出Test是非文字的。

为什么空的析构函数和根本没有析构函数有什么区别?

编辑:另一个相关问题:如果空和文字析构函数不同,如何定义受保护的文字析构函数?

2 个答案:

答案 0 :(得分:20)

来自n3376的报价

7.1.5 / 9

对象声明中使用的constexpr说明符将对象声明为const。这样的对象应该有 字面类型,应初始化。如果它是由构造函数调用初始化的,那么该调用应该是一个常量 表达

3.9 / 10

如果符合以下类型,则为文字类型:

它有一个简单的析构函数......

12.4 / 5

如果析构函数不是用户提供的,并且如果:

,则析构函数是微不足道的

- 析构函数不是虚拟的,

- 其类的所有直接基类都有简单的析构函数,

- 对于类的所有类型(或其数组)的非静态数据成员,每个都是这样的 class有一个简单的析构函数。

否则,析构函数是非常重要的。

clang诊断确实提供了更丰富的信息:

error: constexpr variable cannot have non-literal type 'const C'

'C' is not literal because it has a user-provided destructor

答案 1 :(得分:0)

没有析构函数会导致编译器添加一个普通的析构函数,这个析构函数在规范中定义不正确,但基本上什么也没做。

如果指定析构函数,则不会添加简单的析构函数。你的析构函数是非平凡的。

在你的情况下,Test::~Test() { }看起来非常微不足道,但这是对你看到的内容的人类解释。为了更进一步,那么:

Test::~Test()
{
    int a = 5;
}

我们可以看到优化器可以优化a,所以它显然什么都不做。怎么样:

Test::~Test()
{
    for (int i = 0; i < 1000; i += 2) {
        if ((i % 2) == 1)
            doSomeSideEffect(); // like throwing or setting a global
    }
}

我们可以看到i永远不会是奇数,所以析构函数什么都不做。

规范必须定义什么是constexpr,什么不能。他们只是声明对constexpr足够好的唯一无所事事的析构函数是编译器提供的无关的析构函数,而不是沿着这个定义“无所事事”的兔子洞。