C++ 为什么类构造函数为其成员生成析构函数? 让我们从热身开始。
我创建了一个类模板,如果没有编译器激活C++ 为什么类构造函数为其成员生成析构函数? 让我们从热身开始。,c++,C++,我创建了一个类模板,如果没有编译器激活static\u assert,它的析构函数就无法实例化: 档案:M.hpp 模板 结构M { M(){} ~M() { static_assert(sizeof(T)==0,“没有类型可以传递它”); } }; 接下来,我以两种不同的方式使用这个类:在堆上分配它和在堆栈上分配它: 文件main.cpp #包括“M.hpp” int main() { M*pmi=new M();//编译 M mi;//不编译 } 在堆上分配它M*pmi=newm()工作
static\u assert
,它的析构函数就无法实例化:
档案:M.hpp
模板
结构M
{
M(){}
~M()
{
static_assert(sizeof(T)==0,“没有类型可以传递它”);
}
};
接下来,我以两种不同的方式使用这个类:在堆上分配它和在堆栈上分配它:
文件main.cpp
#包括“M.hpp”
int main()
{
M*pmi=new M();//编译
M mi;//不编译
}
在堆上分配它M*pmi=newm()代码>工作。这是因为我们只使用构造函数,不需要析构函数。类模板隐式实例化的规则:
。。。除非该成员在程序中使用,否则它不会实例化
在堆栈M mi上分配它代码>不起作用,因为编译器肯定需要实例化析构函数
到目前为止,规则是好的、明确的
让我们开门见山吧。
我写了另一个类,它使用M
作为成员:
文件X.cpp
#包括“M.hpp”
结构X
{
X()=默认值;
~X()=删除;
私人:
M_;
};
我故意删除了析构函数,因为我不想让它干扰我的实验。
构造函数是默认的,在我的理解中,它应该只生成M
的构造函数,它是它唯一的成员,并调用它。
令我惊讶的是,事实并非如此X()
还尝试生成M
的析构函数:
文件main.cpp
#包括“X.hpp”
int main()
{
X*px=新的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");
$g++-std=c++17 main.cpp
在X.hpp:1中包含的文件中,
来自main.cpp:1:
M.hpp:在“M::~M()[with T=int]”的实例化中:
X.hpp:5:3:从这里开始需要
M.hpp:7:29:错误:静态断言失败:没有类型可以传递此消息
static_assert(sizeof(T)==0,“没有类型可以传递它”);
问题是:为什么在实例化默认构造函数的过程中,如果不需要,编译器会尝试实例化成员类模板的析构函数?如果确实需要的话,你能告诉我文件上的说明吗 您的X
的构造函数可能会调用其成员子对象的析构函数,原因很明显:如果在构造过程中发生异常,则必须对已成功构造的所有对象进行析构函数
10.9.2初始化基础和成员
12在非委托构造函数中,可能调用类类型的每个可能构造的子对象的析构函数(15.4)。[注:此规定确保在引发异常时,可以为完全构造的子对象调用析构函数(18.2)。-结束说明]
我认为(也许我错了)如果可能的话,CTOR的默认实现是noexcept
,这应该是m
的情况,因此X
也是如此。那么,如果不能抛出异常,为什么dtor仍有可能被调用呢?