C++显式调用析构函数问题一二

问题描述

关于显示调用析构函数会不会对对象本身进行析构?
有两种结论:
(1)会析构对本身;
(2)不会析构对象本身,只是单纯调用析构函数;

#include <iostream>
class Log1
{
public:
	int a;
	Log1():a(1)
	{
		std::cout << "构造函数";
	}


	~Log1()
	{
		std::cout << "析构函数";
	}
};

void fun()
{
	Log1 l;//调用构造函数
	l.~Log1();//此处显式调用了析构函数
	std::cout << "l.a的值为" << l.a << std::endl;//验证显式调用析构函数,会不会destroy object
}
int main()
{
	fun();//执行完fun()函数后,会自动调用析构函数
	getchar();
}

运行结果:
在这里插入图片描述
根据运行结果可以看出似乎结论2更为合理。

具体分析:

1.析构函数的作用

摘在Wikipedia:
Its main purpose is to free the resources (memory allocations, open files or sockets, database connections, resource locks, etc.) which were acquired by the object during its life and/or deregister from other entities which may keep references to it. Use of destructors is needed for the process of Resource Acquisition Is Initialization (RAII).
析构函数作用就是释放资源(内存分配,打开的文件,网口句柄,数据库连接等)。从定义上看析构函数并不会destroy对象

2.调用析构函数的时机

摘在Wikipedia:
As stated above, a destructor for an object is called whenever the object’s lifetime ends.[2] If the object was created as an automatic variable, its lifetime ends and the destructor is called automatically when the object goes out of scope. Because C++ does not have garbage collection, if the object was created with a new statement (dynamically on the heap), then its destructor is called when the delete operator is applied to a pointer to the object. Usually that operation occurs within another destructor, typically the destructor of a smart pointer object.

1.对象的生命周期结束,例如对象是一个局部变量;
2.new的对象,通过delete删除对象时;
3.对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

3.结论

l.~Log1();//此处显式调用了析构函数
std::cout << "l.a的值为" << l.a << std::endl;//验证显式调用析构函数,会不会destroy object

因此,当调用 l.~Log() 函数后,还可以打印 l.a 的值,因为此处析构函数并没有destroy对象;

至于部分网友说:调用两次析构函数会导致Undefined Behavior, 其实不然:
Invoking the destructor on an object whose lifetime has ended results in undefined behavior per C++03 §12.4/6:

the behavior is undefined if the destructor is invoked for an object whose lifetime has ended
首先,这里强调的是:只有对象声明周期结束时即对象呗销毁了再次调用destructor会造成Undefined Behavior;
An object’s lifetime ends when its destructor is called per §3.8/1:

The lifetime of an object of type T ends when:

— if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or

— the storage which the object occupies is reused or released.
这里解释了那些情况生命周期结束:
——含有non-trivial析构函数的类调用该析构函数
——存储对象的内存释放或是挪为他用;

Note that this means if your class has a trivial destructor, the behavior is well-defined because the lifetime of an object of such a type does not end until its storage is released, which for automatic variables does not happen until the end of the function. Of course, I don’t know why you would explicitly invoke the destructor if it is trivial.
因此,在对于那些有trivial destructorde 类的局部变量对象而言,直到局部变量所在作用域结束之前,该对象不会被销毁的。
What is a trivial destructor? §12.4/3 says:

A destructor is trivial if it is an implicitly-declared destructor and if:

— all of the direct base classes of its class have trivial destructors and

— for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.

总结

1.析构函数并不是销毁对象的,只是释放构造函数在构造时初始化的资源(主要包括堆上分配内存等)
2.只有类对象被销毁后再次调用用析构函数才会引起Undefined Behavior。

**备注:**写的比较杂,后期再整理,欢迎拍砖斧正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章