私有析构函数和删除析构函数

析构函数 destructor

私有析构函数 private destructor

析构函数是 private 时,那么当对象销毁时或对于动态分配的对象,当对指向它的指针应用 delete 运算符时,只有 对象销毁 所处的上下文环境为成员函数体或友元函数体内部时,才能正常调用 private 析构函数,才能正常销毁对象。其原因是,只有成员函数和友元函数才能访问类的 private 成员。

所以,(1)当定义一个对象(非动态分配)时,只有 对象定义 所处的上下文环境能够访问 private 析构函数时,编译器才会允许定义该类型的对象。其原因是,如果没有这条规则,我们可能会创建出无法销毁的对象。(2)动态分配的对象, new 表达式所处的环境并没有什么限制,但当对指向它的指针应用 delete 运算符时,只有 delete 表达式所处的上下文环境能够访问 private 析构函数时,才能正常销毁对象。

其实,将析构函数声明为 private 几乎没有什么实用意义,因为通常我们的程序设计应该总是使析构函数能够被通畅地调用,而不是设置“障碍”。

#include <iostream>
#include <string>
#include <memory>

class T
{
	friend void FriendDestroy(T* ptr);
public:
	static void StaticDestroy(T* ptr)
	{
		delete ptr;
	}

	// Destroy() is 'delete this', which looks like very dangerous, not recommended. The more recommended is 'static void StaticDestroy(T* ptr)'.
	void Destroy()
	{
		delete this;
	}
public:
	void InstanceInMemberFunction()
	{
		// ok: destructor 'T::~T()' can normally call within this context
		T t;
	}
public:
	T() = default;
	T(const T&) = default;
	T(T&&) = default;
	T& operator=(const T&) = default;
	T& operator=(T&&) = default;
private:
	~T() { std::cout << "destructor is called" << std::endl; }
private:
	std::string str_;
};

void FriendDestroy(T* ptr)
{
	delete ptr;
}

int main()
{
	// error: destructor 'T::~T()' is private within this context
	//T t1;

	// error: destructor 'T::~T()' is private within this context where '~unique_ptr()' delete pointer
	//auto t2 = std::make_unique<T>();

	// no delete pointer and the memory leak would occur
	auto t3 = new T();
	// error: destructor 'T::~T()' is private within this context
	//delete t3;

	auto t4 = new T();
	// Destroy() is 'delete this', which looks like very dangerous, not recommended. The more recommended is 'static void StaticDestroy(T* ptr)'.
	t4->Destroy();
	t4 = nullptr;

	auto t5 = new T();
	t5->InstanceInMemberFunction();
	T::StaticDestroy(t5);
	t5 = nullptr;

	auto t6 = new T();
	FriendDestroy(t6);
	t6 = nullptr;

	return 0;
}

删除析构函数 deleted destructor

值得注意的是,我们不能删除析构函数。如果析构函数被删除,就无法销毁此类型的对象了。对于一个删除了析构函数的类型,编译器将不允许定义该类型的变量或创建该类的临时对象。而且,如果一个类有某个成员的类型删除了析构函数,我们也不能定义该类的变量或临时对象。因为如果一个成员的析构函数是删除的,则该成员无法被销毁。而如果一个成员无法被销毁,则对象整体也就无法被销毁了。

对于删除了析构函数的类型,虽然我们不能定义这种类型的变量或成员,但可以动态分配这种类型的对象。但是,不能释放这些对象。

其实,删除析构函数几乎没有什么实用意义,因为我们很少需要创建不能销毁的对象(这时就只能通过动态分配来创建对象了,但不能释放这些对象)。

#include <iostream>
#include <string>
#include <memory>

class T
{
public:
	~T() = delete;
public:
	T() = default;
	T(const T&) = default;
	T(T&&) = default;
	T& operator=(const T&) = default;
	T& operator=(T&&) = default;
private:
	std::string str_;
};

int main()
{
	// error: use of deleted destructor function 'T::~T()'
	//T t1;

	// error: use of deleted destructor function 'T::~T()'
	//auto t2 = std::make_unique<T>();

	// no delete pointer and the memory leak would occur
	auto t3 = new T();
	// error: use of deleted destructor function 'T::~T()'
	//delete t3;

	return 0;
}
原文地址:https://www.cnblogs.com/ltimaginea/p/15429828.html