C++基础篇:09 智能指针与异常处理

这篇具有很好参考价值的文章主要介绍了C++基础篇:09 智能指针与异常处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 智能指针

1.1 常规指针的缺点

        当一个常规指针离开作用域时,只有该指针变量所占用的内存空间(4/8字节)会释放,而它所指向的内存空间不会自动释放,当free、delete、delete[]语句忘记写、无法执行,就造成内存泄漏

1.2 智能指针的优点

    ① 智能指针是一个封装了常规指针的类类型,并在该类中重载了 * -> []运算符

    ② 当智能指针对象离开作用域,它的析构函数会自动地释放常规指针所指向的内存,从而达到自动释放的效果,目的是为了避免内存泄漏

1.3 智能指针与常规指针的相同点

        它们的操作就跟操作普通指针一样

2 C++STL中的智能指针

        STL中提供了auto_ptr\unique_ptr\shared_ptr\weak_ptr种智能指针,在C++98语法标准中只有auto_ptr,后面三个是C++11语法标准中增加的,并且弃用了auto_ptr,使用会有警告

        头文件:<memory>

2.1 auto_ptr

        采用独占式拥有模式,不能同时有多个auto_ptr指向同一个对象,但是不能完全实现,所以有隐患,所以C++11中产生使用警告

auto_ptr<类型名> p(new 类型名);
类型名* p = new 类型名;
auto_ptr<类型名> atuo_p(p);
auto_ptr<类型名> p2;
p2 = p1;     //  不报错,p2也指向p1内存,p1可能还指向、也可能不指向,不确定   

2.2 unique_ptr  独享指针  

        相当于auto_ptr的升级,完全实现独占式拥有模式,保证同一时间内只有一个unique_ptr指向某个对象

        通过把拷贝构造、赋值操作函数声明为delete来禁用uniqued的赋值

        unique_ptr<int> p1(new int);

        unique_ptr<int> p2(p1);    //   报错

        p2 = p1;    //  报错

        p2 = unique_ptr<string>(new string("hehe"));//允许,允许匿名赋值,此时p2是唯一指向者

        但是允许unique_ptr的匿名对象给一个unique_ptr赋值,并且可以通过C++标准库全局函数move() 转移某个unique_ptr的指向给另一个unique_ptr,而原来的unique_ptr会指向NULL,还是确保了独占

        p1 = move(p2);

        并且p1原来指向的内存,会在move执行转移之前先释放,确保不会内存泄漏,然后才更改指向p2原来指向的内存,最后p2指向NULL

2.3 shared_ptr 共享指针

        采用共享式拥有模式,允许同一时间多个shared_ptr指向相同内存

        当一个内存资源被shared_ptr指向时,内部的一个引用计数器+1

        当指向该资源的某个shared_ptr离开作用域时,引用计数器-1,并放弃对该资源的引用

        当某个shared_ptr调用reset()成员函数时,引用计数器-1,并放弃对该资源的引用

        当该资源的引用计数减为0时,最后放弃引用的shared_ptr才会在析构函数释放该资源,以此保证不会被重复释放

2.3.1 相关shared_ptr成员函数

            get()   获取指向内存的地址

            use_count() 返回引用计数的数量

            unique()    判断是否独占 (1:独占 0:共享)

            reset()     放弃对内存的指向并且指向NULL,引用计数-1

2.3.2 C++全局标准库函数

            swap()  交换两个对象的值

            swap(p1,p2);    //交换共享指针的指向

2.3.3 shared_ptr的循环引用问题

        当两个类中都有能够相互指向对方类类型的共享指针成员变量,并且在类外分别指向两个共享指针指向new出来的两个类对象,并且让这个两个类对象的共享指针成员指向对方,这样就构成了循环引用,当这两个类对象离开作用域时,会因为产生死锁而无法执行各自的析构函数,导致内存泄漏

2.4 weak_ptr 弱引用指针

        weak_ptr是为了配合shared_ptr而引入的一种智能指针,用它来指向被shared_ptr指向的资源,而不会影响该资源的生命周期,也就是说一个wear_ptr指向某个资源或者断开指向时,都不会改变该资源的引用计数,只有当该资源被最后一个shared_ptr断开指向后,引用计数为0才会被释放。但是weak_ptr是可以正常像智能指针一样访问资源,因此weak_ptr相当于shared_ptr的助手,解决一些shared_ptr无法解决的问题,例如解决shared_ptr的循环引用问题。weak_ptr不能单独使用

3 C++的异常处理

        当代码运行时出现错误,终止执行(意外)

        C语言中执行到不正确结果时,可以通过返回值提前结束执行,并且可以把错误原因通过返回值传递给调用者

        C语言中调用者只能立即接收返回值,或者立即使用显示

        C++可以针对代码运行出错抛出异常,并通过捕获对应的异常,执行不同的错误处理语句,如果捕获成功可以不终止

4 如何抛异常

throw 数据;

        数据可以是任意类型,不受函数返回值的限制,但是不要抛出局部变量的地址或引用,因为局部变量会自动销毁

5 如何捕获异常

try{
//  可能会产生异常的代码或函数调用
}catch(类型名 变量名){
//  错误处理
}

6 异常规范(异常说明)

返回值 函数名(参数列表)throw(类型名1,类型名2,...){}

        异常规范:在某个函数声明时,增加一个异常规范,用于限制该函数可以抛出的异常的类型有哪些

        如果在进行过异常规范的函数中,抛出不属于规范内类型的异常时,可以抛出,但是无法捕获不属于规范的类型异常

    因此通过  返回值 函数名(参数列表)throw(){} //说明该函数不能抛任何异常

7 C++的标准异常

    C++已经定义好了一些异常类,当某些特定异常发生时,编译器会自动抛出对应的异常类对象

    std::exception  所有标准异常类的父类,可以使用该类对象来捕获所有的标准异常子类对象

    std::bad_alloc  new分配失败抛出该异常类对象或它的子类类对象

    std::bad_cast 该异常可以通过dynamic_cast 抛出。 需要导入<typeinfo>

    std::invalid_argument 当使用了无效的参数时,会抛出该异常

    std::length_error 当创建了太长的string时,会抛出该异常

8 自定义异常类

#include <iostream>
using namespace std;

#define Err(...) ZhiZhenError(__FILE__,__func__,__LINE__,__TIME__,__VA_ARGS__)

class ZhiZhenError : public exception
{
	string file;
	string func;
	size_t line;
	string time;
	string info;
public:
	ZhiZhenError(const string& file,const string& func,size_t line,const string& time,const string& info)throw():file(file),func(func),line(line),time(time),info(info) {}
	~ZhiZhenError(void)throw(){}

	friend ostream& operator<<(ostream& os,const ZhiZhenError& err)
	{
		return os << "file:" << err.file << " func:" << err.func <<" line:" << err.line << " error:" << err.info << " time:" << err.time;	
	}
};

void func(int num)throw(ZhiZhenError)
{
	if(num > 0)
	{
		cout << "good" << endl;	
	}
	else
	{
		//throw ZhiZhenError(__FILE__,__func__,__LINE__,__TIME__,"num too small");
		throw Err("too small");
	}
}

int main(int argc,const char* argv[])
{
	try{
		func(-100);
	}catch(ZhiZhenError err){
		cout << err.what() << endl;
		cout << err << endl;		
	}
}

9 使用异常需要注意的问题

① 不要抛出局部变量的地址、引用

② 如果使用引用类型来捕获异常,就会少一次拷贝

③ 不要在构造函数、析构函数中抛异常

④ C++中异常经常会导致资源泄漏问题,比如在new\detele过程中抛出异常并捕获而没有处理,可能导致内存泄漏,可以借助智能指针避免,在lock和unlock之间抛出异常,导致锁没法解开,别的线程可能在等待该锁的解锁,导致死锁问题文章来源地址https://www.toymoban.com/news/detail-489595.html

到了这里,关于C++基础篇:09 智能指针与异常处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 安全测试国家标准解读——函数调用安全、异常处理安全、指针安全

    下面的系列文章主要围绕 《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》 进行讲解,该标准是2020年4月28日,由国家市场监督管理总局、国家标准化管理委员会发布,2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理,大家感兴趣的话可以自己去下载

    2024年02月13日
    浏览(59)
  • 【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

    【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针 大家好,今天是【重学C++】系列的第二讲,我们来聊聊C++的智能指针。 在上一讲《01 C++如何进行内存资源管理》中,提到了对于堆上的内存资源,需要我们手动分配和释放。管理这些资源是个技术活,一不小心,就会导致内

    2024年02月05日
    浏览(59)
  • 【C++】智能指针详解

    今天我们来讲一下c++中的智能指针。 智能指针不是指针,是一个管理指针的类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。 动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源 C++ 98 中产

    2024年02月04日
    浏览(78)
  • C++智能指针的发展

    GC–garbage collection垃圾回收,Java里的机制。在头文件 memory 中 堆内存泄漏(Heap leak) 堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那

    2023年04月19日
    浏览(36)
  • C++新特性:智能指针

    智能指针主要解决以下问题: 1)内存泄漏:内存手动释放,使用智能指针可以自动释放 2)共享所有权指针的传播和释放,比如多线程使用同一个对象时析构问题,例如同样的数据帧,但是业务A和业务B处理的逻辑不一样(都是只读)。可以用 shared_ptr 共享数据帧对象的所有

    2024年02月09日
    浏览(43)
  • 面试:C++ 11 智能指针

    内存泄露在维基百科中的解释如下: 在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了

    2024年02月07日
    浏览(42)
  • C++——智能指针

    内存泄漏 什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内 存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对 该段内存的控制,因而造成了内存的浪费。 内存泄漏的危害:长期运行的

    2024年02月09日
    浏览(72)
  • C++进阶 智能指针

    本篇博客简介:介绍C++中的智能指针 我们首先来看下面的这段代码 在上面这段代码中有着一个很明显的内存泄露风险 当我们的程序运行在Func函数内的div函数时 很可能因为除0错误而跳转到另外一个执行流从而导致Func函数内两个new出来的内存没法被回收 为了解决这个问题我

    2024年02月13日
    浏览(50)
  • 智能指针——C++

    智能指针相较于普通指针的区别,就是智能指针可以不用主动释放内存空间,系统会自动释放,避免了内存泄漏。 需包含的头文件: #include memory unique_ptr 三种定义方式 先定义一个类 使用std::make_unique的方式:推荐使用的方式 程序结束自动调用析构函数 使用new的方式声明智能

    2023年04月22日
    浏览(49)
  • 【C++学习】智能指针

    🐱作者:一只大喵咪1201 🐱专栏:《C++学习》 🔥格言: 你只管努力,剩下的交给时间! 如上图代码所示,在Func中开辟动态空间,在调用完Division函数后释放该空间。 如果Division没有抛异常,那么动态空间会被正常释放。 如果Division抛了异常,就会去匹配对应的catch,而Fu

    2024年02月06日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包