c++指针—智能指针

205 阅读2分钟

这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

Smart Points 是什么,或者说是用来干什么的? 开始在 c++ 中是没有智能指针,但是共所周知在 c++ 中对于指针使用我们要格外小心,不然就可能出现内存溢出、或者引用的内存被释放,导致引用无法访问。

智能指针是用来管理动态分配的内存的,也就是帮助我们管理内存,避免自己管理内存使用而发生问题。能够动态地分配资源且能够在适当的时候释放掉曾经动态分配的内存。

要使用智能指针,需要引入 #include <memory>

独占指针

首先介绍一个 unique_ptr 指针,创建这个指针方法与普通指针创建的方法略有不同,不过同样在创建这个指针需要指定该指针指向内存地址中存放数据类型。

unique_ptr<int> uniquePtr1 = make_unique<int>(25);

这样 make_unique<T> (),可用于创建 unique_ptr 对象。该函数分配一个类型为 T 的对象,然后返回一个拥有该对象的独占指针。

cout << *uniquePtr1 << endl;
unique_ptr<int> uniquePtr1 = make_unique<int>(25);
unique_ptr<int> uniquePtr2 = uniquePtr1;

这样就会报错,也就是说明这个 uniquePtr1 是独占这个块内存,好处就是避免其他指针指向内存后将其释放,也就是不好控制这块内存,这样专人专管好处不然而喻了。也就是说 uniquePtr1 对这块内存但不使用,而且是拥有这块内存,不过也可以将这块内存通过move 方法转让给其他指针。

unique_ptr<int> uniquePtr1 = make_unique<int>(25);
unique_ptr<int> uniquePtr2 = move(uniquePtr1);
cout << *uniquePtr2 << endl;

经过上面将 uniquePtr1 指向内存地址的拥有权移交给了 uniquePtr2 后,我们进行输出 *uniquePtr1 就会报错。

cout << *uniquePtr2 << endl;
cout << *uniquePtr1 << endl;

接下来创建一个 MyClass 然后定义构造函数和析构函数,在这两个方法分别输出一句话。

class MyClass
{
public:
	MyClass() {
		cout << "Constructor invoked" << endl;
	}

	~MyClass()
	{
		cout << "Destructor invoked" << endl;
	}
};
int main()
{
	{
		unique_ptr<MyClass> uniquePtr1 = make_unique<MyClass>();
	}
	
	system("pause>nul");
}

这样定义作用域位于,在这个作用域内定义unique_ptr指向 MyClass 类型,当离开这个作用域就会自动调用该类析构函数。

共享指针

share_ptr 基于引用计数模型实现,在 python 内存管理中,python 每一个对象都有一个引用计数,当没有变量引用该对象时,就会在垃圾回收时将其清除。有点类似,所谓 share 也就是允许多个 share_ptr 指向同一个动态对象,并且维护一个共享的引用计数器,记录了引用同一个对象的 shared_ptr 实例的数量。

{
        shared_ptr<MyClass> sharePtr1 = make_shared<MyClass>();
        cout << "Share count " << sharePtr1.use_count() << endl;

}
shared_ptr<MyClass> sharePtr1 = make_unique<MyClass>();
cout << "Share count " << sharePtr1.use_count() << endl;
shared_ptr<MyClass> sharePtr2 = sharePtr1;
cout << "Share count " << sharePtr1.use_count() << endl;
int main()
{
	shared_ptr<MyClass> sharePtr1 = make_unique<MyClass>();
	cout << "Share count " << sharePtr1.use_count() << endl;
	{
		
		shared_ptr<MyClass> sharePtr2 = sharePtr1;
		cout << "Share count " << sharePtr1.use_count() << endl;

	}
	cout << "Share count " << sharePtr1.use_count() << endl;
	
	system("pause>nul");
}

这里我们将 sharePtr2 移入到一个作用域内,当其销毁后,引用指针就会减少 1。

int main()
{
	{
		shared_ptr<MyClass> sharePtr1 = make_shared<MyClass>();
		cout << "Share count " << sharePtr1.use_count() << endl;
		{
		
			shared_ptr<MyClass> sharePtr2 = sharePtr1;
			cout << "Share count " << sharePtr1.use_count() << endl;

		}
		cout << "Share count " << sharePtr1.use_count() << endl;
	}
	system("pause>nul");
}

当没有指针再指向该对象时候,就会销毁该对象。

shared_ ptr 和 new 结合使用

如果我们不初始化一个智能指针,它就会被初始化为一个空指针。如下,我们还可以用new返回的指针来初始化智能指针

shared_ptr<int> p2 (new int(42));