C++的智能指针(1/3)

目录

为什么要使用智能指针

智能指针的作用

举个例子

最开始使用的智能指针——auto_ptr

使用方法

举个例子

进阶使用

这时候的调用结果

对比使用智能指针

例子

结果

调用函数方法

例子

结果

智能指针常用的是三个函数

get() 返回智能指针托管的指针地址

例子

结果

release() 取消智能指针对动态内存的托管

例子

结果

reset() 重置智能指针托管的内存地址,如果地址不一致,原来的会被析构掉

注意事项

auto_ptr的缺点以及为什么在C++11中被淘汰

下一节

参考文章(感谢大佬)


为什么要使用智能指针

使用智能指针的主要目的是管理动态分配的内存,以确保在不再需要时正确释放内存,避免内存泄漏和悬挂指针等问题。

智能指针的作用

智能指针是一种封装了原始指针的对象,它提供了自动内存管理的功能。与传统的裸指针相比,智能指针具有以下优势:

  1. 自动释放内存:智能指针使用了RAII(资源获取即初始化)的原则,在创建时分配内存,在销毁时自动释放内存,无需手动管理内存释放,避免了因为忘记释放内存而造成的内存泄漏问题。

  2. 避免悬挂指针:智能指针会在其所管理的对象不再需要时自动释放内存,并将指针置为空,避免了悬挂指针问题,即指向已经释放的内存区域。

  3. 异常安全:智能指针可以确保在发生异常时正确释放资源,因为它们的析构函数会在对象被销毁时自动调用。

  4. 方便易用:智能指针提供了类似于原始指针的操作符重载,使得使用起来更加方便和直观。

总之,使用智能指针可以提高代码的可靠性和安全性,并减少手动管理内存的工作量,是现代C++编程中推荐的做法。

举个例子

#include <iostream>
#include <memory>
#include <vector>
using namespace std;
void Function_1()
{
	int *a=new int;
	*a = 12;
	//省略其他代码
	if (true)
	{
		return;
		//此时已经跳出循环所以不执行下面的删除指针a
	}
	delete a;
}
int main()
{
	Function_1();
	//这时a指针没有被释放
	return 0;
}

这个时候在执行程序的这一过程中a指针没有被及时释放,这只是一个简单的例子,

在真实的情况中也不会只有这一个a没有被释放,甚至在一些循环中如果释放指针那造成的结果是灾难性的,你排除一些报错会十分的困难。

每次记住及时释放指针是一个好习惯并且也是一个好的解决办法。但是这是十分困难的

这个时候就可以使用智能指针这个方案

最开始使用的智能指针——auto_ptr

auto_ptr 是c++ 98定义的智能指针模板,其定义了管理指针的对象,可以将new 获得(直接或间接)的地址赋给这种对象。当对象过期时,其析构函数将使用delete 来释放内存!

使用方法

在使用之前需要在头文件中定义

 #include < memory >

用法为

auto_ptr<类型> 变量名(new 类型)

举个例子

auto_ptr<int> sum(new int(20));//这是定义一个int类型的智能指针
auto_ptr< string > str(new string("你好,我叫mumuemhaha"));//这是定义一个string类型的智能指针

进阶使用

到这里想必你已经可以理解auto_ptr如何定义了

我们再次把难度稍微提升一些

这时我们调用第一个类

#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class Test_1 {
public:
	Test_1() { cout << "Test_1的构造函数" << endl; }
	~Test_1() { cout << "Test_1的析构函数" << endl; }

	int getsum() { return this->sum; }

private:
	int sum = 20;
};

int main()
{
	Test_1* test_1 = new Test_1;
	return 0;
}

这时候的调用结果

Test_1的构造函数

D:\C++\调试\x64\Debug\调试.exe (进程 23424)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

这个时候由于我们没有删除指针,故就析构函数没有调用

对比使用智能指针

这时我们只要用智能指针(前面的类不打了)

例子

int main()
{
	auto_ptr<Test_1> test_1(new Test_1);
	return 0;
}

结果

Test_1的构造函数
Test_1的析构函数

D:\C++\调试\x64\Debug\调试.exe (进程 21956)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

这个时候即使我们没有删除指针但是但函数周期结束后他默认把我们的指针删除了

调用函数方法

指针的变量调用函数的方法依旧和普通指针一样

例子

int main()
{
	auto_ptr<Test_1> test_1(new Test_1);
	cout << test_1->getsum()<< endl;
	return 0;
}

结果

Test_1的构造函数
20
Test_1的析构函数

D:\C++\调试\x64\Debug\调试.exe (进程 8472)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

智能指针常用的是三个函数

get() 返回智能指针托管的指针地址

例子

int main()
{
	auto_ptr<Test_1> test_1(new Test_1);
	cout << test_1.get()<< endl;
	return 0;
}

结果

Test_1的构造函数
0000029FEC3B6360
Test_1的析构函数

D:\C++\调试\x64\Debug\调试.exe (进程 17760)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

release() 取消智能指针对动态内存的托管

例子

int main()
{
	auto_ptr<Test_1> test_1(new Test_1);
	Test_1* a = test_1.release();
	return 0;
}

结果

Test_1的构造函数

D:\C++\调试\x64\Debug\调试.exe (进程 23712)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

这时你会发现只有构造函数没有析构函数,这时因为test_1已经被a托管了,如果需要释放必须要手动释放(或者用另外一个智能指针去托管它)

reset() 重置智能指针托管的内存地址,如果地址不一致,原来的会被析构掉

这个不举例子了就是重置指针,注意的是其中可以"变量.reset()”也可以"变量.reset(new Test_1)”

注意事项

  • 尽量不要把auto_ptr指针定义为全局变量或者指针(这将与其他指针相比毫无意义)
  • 除非你知道后果,否则不要把auto_ptr 智能指针赋值给同类型的另外一个智能指针比如像这样
  • auto_ptr<Test_1> t1(new Test);
    auto_ptr<Test_1> t2(new Test);
    t1 = t2;	// 不要这样

auto_ptr的缺点以及为什么在C++11中被淘汰

一        在第二个注意事项中,因为t1=t2这个表达式就是t2指针指向数据的所有权转换给t1,并且把把t2的指针清空.这个和我平时的直觉不相符

二        正是这个原因,所以最好也不要在STL容器中使用auto_ptr指针(因为容器的值必须要支持可以赋值)

三        不支持对象数组的内存管理,比如

auto_ptr<int[]> array(new int[5]);

所以,C++11以及之后使用了接下来要讲的更严谨的unique_ptr 来去取代了auto_ptr!

下一节

C++智能指针(2/3)_木木em哈哈的博客-CSDN博客自动释放内存:智能指针使用了RAII(资源获取即初始化)的原则,在创建时分配内存,在销毁时自动释放内存,无需手动管理内存释放,避免了因为忘记释放内存而造成的内存泄漏问题。unique_ptr是一种独占所有权的智能指针,同一时间只能有一个unique_ptr指向一个对象,当unique_ptr被销毁时,对象也会被释放。在这之中开始时p1托管str的指针,后面p2接管str指针的同时会把p1的托管给取消,这样p1指针指向的就是NULL(空),从而报错。这是因为auto_ptr与unique_ptr的排他性。https://blog.csdn.net/mumuemhaha/article/details/131689322?spm=1001.2014.3001.5502

参考文章(感谢大佬)

C++ 智能指针 - 全部用法详解_cpp智能指针特性_cpp_learners的博客-CSDN博客血的教训?不学智能指针,本人丢了一份工作。_cpp智能指针特性https://blog.csdn.net/cpp_learner/article/details/118912592

猜你喜欢

转载自blog.csdn.net/mumuemhaha/article/details/131668974