【发布时间】:2019-03-15 22:16:03
【问题描述】:
让我们从热身开始吧。
我创建了一个类模板,如果没有编译器激活static_assert,它的析构函数就无法实例化:
文件:M.hpp
template <typename T>
struct M
{
M(){}
~M()
{
static_assert(sizeof(T) == 0, "no type can pass this");
}
};
接下来我以两种不同的方式使用这个类:在堆上分配和在堆栈上分配:
文件 main.cpp
#include "M.hpp"
int main()
{
M<int> *pmi = new M<int>(); // does compile
M<int> mi; // doen't compile
}
在堆上分配它M<int> *pmi = new M<int>(); 有效。因为我们只使用构造函数而不需要析构函数。类模板隐式实例化规则say:
...除非在程序中使用该成员,否则不会实例化...
在堆栈M<int> mi; 上分配它不起作用,因为编译器肯定需要实例化析构函数。
到目前为止一切顺利,规则清晰。
让我们进入正题。
我写了另一个使用M作为成员的类:
文件 X.cpp
#include "M.hpp"
struct X
{
X() = default;
~X() = delete;
private:
M<int> m_;
};
我故意删除了析构函数,因为我不希望它干扰我的实验。
构造函数是默认的,在我的理解中应该只生成 M<int> 的构造函数,它的唯一成员,然后调用它。
令我惊讶的是,事实并非如此。 X() 也尝试生成M<int> 的析构函数:
文件 main.cpp
#include "X.hpp"
int main()
{
X* px = new X();
}
这是我从编译器中得到的:
$ g++ -std=c++17 main.cpp
In file included from X.hpp:1,
from main.cpp:1:
M.hpp: In instantiation of ‘M<T>::~M() [with T = int]’:
X.hpp:5:3: required from here
M.hpp:7:29: error: static assertion failed: no type can pass this
static_assert(sizeof(T) == 0, "no type can pass this");
问题是:为什么在默认构造函数的实例化过程中,如果不需要,编译器会尝试为成员类模板实例化析构函数?如果确实需要它,您能否指点我说明它的文档?
【问题讨论】:
标签: c++