struct Base
{
Base() {
std::cout << "Base::构造" << std::endl;
}
~Base() { //非virtual
std::cout << "Base::~析构" << std::endl;
}
virtual void execute() = 0;
};
class Inherit : public Base
{
public:
Inherit() {
std::cout << "Inherit::构造" << std::endl;
}
~Inherit() { //非virtual
std::cout << "Inherit::~析构" << std::endl;
}
void execute() override {
std::cout << "Inherit::execute()" << std::endl;
}
};
int main() {
std::cout << "-----原始指针-----" << std::endl;
{
Base* p = new Inherit();
p->execute();
delete p;
}
std::cout << "-----unique_ptr-----" << std::endl;
{
std::unique_ptr<Base> p = std::make_unique<Inherit>();
p->execute();
}
std::cout << "-----shared_ptr-----" << std::endl;
{
std::shared_ptr<Base> p = std::make_shared<Inherit>();
p->execute();
}
std::cout << "-----结束-----" << std::endl;
return 0;
}
测试环境VS2015及VS2019。 运行结果如下:
-----原始指针-----
Base::构造
Inherit::构造
Inherit::execute()
Base::~析构
-----unique_ptr-----
Base::构造
Inherit::构造
Inherit::execute()
Base::~析构
-----shared_ptr-----
Base::构造
Inherit::构造
Inherit::execute()
Inherit::~析构
Base::~析构
-----结束-----
原因是这样的:shared_ptr的构造函数是一个模板函数,shared_ptr会记住这个指针类型即你例子中的Base类型,shared_ptr析构的时候会调用delete Base的指针,而不管这个Base是否有虚的析构函数。
简言之,在share_ptr模板类型和实际类型的析构函数都会被调用到。而unique_ptr则不会去调用模板类型的析构函数。
也许你还想进一步了解为什么unique_ptr不会去调用基类的析构函数,这是因为shared_ptr和unique_ptr的实现方式不同导致的,shared_ptr中的模板参数T允许是一个incomplete type,最终是需要一个完整类型的,通过在最后删除的时候去调用这个incomplete type的析构函数来保证类型的完整性;
而unique_ptr一开始就要求这个模板类型必须是complete type,所以也就不需要去调用模板参数类型的析构函数了。
转: www.purecpp.org