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。

**備註:**寫的比較雜,後期再整理,歡迎拍磚斧正。

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