C++ (指针,智能指针,异常处理) 您所在的位置:网站首页 智能指针有几种 C++ (指针,智能指针,异常处理)

C++ (指针,智能指针,异常处理)

2023-03-24 10:01| 来源: 网络整理| 查看: 265

指针

  指针是一个变量,他的值是另一个变量的地址,即内存位置的直接地址。在C++中指针和引用会有很大的区别:1、指针存储的是一个变量的地址,引用根原来的变量实质上是同一个东西,是原变量的别名;2、指针可以有多级,引用只能有一级;3、指针可以为空并且声明和定义是可以分开的,引用不能为NULL并且在定义时必须初始化;4、指针在初始化后可以改变指向,而引用在初始化后不可以再改变;5、使用sizeof指针得到的是本指针的大小,而sizeof引用得到的是引用所指向变量的大小;6、当把指针作为参数进行传递时,也是将实参的一个拷贝传递给形参,两者指向的地址相同,但不是同一个变量,在函数中改变这个变量的指向不影响实参,而引用却可以;7、引用本质是一个指针,同样会占4字节内存(在64位编译环境下指针大小占8字节,32位环境下指针大小占4字节,而指针占内存的大小根编译环境有关,与机器位数无关);指针是具体变量,需要占用存储空间(,具体情况还要具体分析)。针对引用和指针的不同特性在传递参数时基于不同的情况会选择不同的方式:如果要返回函数内局部变量的内存就用指针,并且使用指针要开辟内存用完需要释放不然容易内存泄漏指针传参本质上是值传递(形参指针变了,实参指针不会变),而如果我们的栈空间比较小往往用引用,因为这不用创建临时变量,开销比较小,并且类对象作为参数传递的时候都是使用引用,因为这是C++类对象传递的标准方式。指针的加减功能本质是对所指地址的移动,移动的步长和指针类型是有关系的,所以在涉及指针加减时要注意不能加多或是加少导致指向了未知的内存地址。   区分如下几种指针类型:

int *p[10] int (*p)[10] int *p(int) int (*p)(int) int const*p/const int* p int *const p

  int *p[10]表示指针数组,强调数组概念,是一个数组变量,数组大小为10,数组内每个元素都是指向int类型的指针变量。   int (*p)[10]表示数组指针,强调是指针,只有一个变量,是指针类型,不过指向的是一个int类型的数组,这个数组大小是10。   int *p(int)是函数声明,函数名是p,参数是int类型的,返回值是int *类型的。   int (p)(int)是函数指针,强调是指针,该指针指向的函数具有int类型参数,并且返回值是int类型的。   int constp是常量指针,这是一个指针,指向的是一个常量,所以指针保存的地址可以改变,指针指向的值不能改变。   int *const p是指针常量,指针本身的值(存放地址)不能改变,指针指向的值可以改变(在第五版C++ Primer中的常量指针与这里描述的不符)   野指针和悬空指针:都是是指向无效内存区域(这里的无效指的是"不安全不可控")的指针,访问行为将会导致未定义行为。野指针指的是没有被初始化的指针,为了防止出错一般指针在初始化时要赋值为nullptr或者直接定义时初始化,这样就不会有非法内存访问。悬空指针:指针最初指向的内存已经被释放的指针(free或delete之后没有及时置空,需要在释放操作后立即置空)在C++中一般使用智能指针来避免悬空指针的产生。   在继承中指针和引用总共有向上类型转换和向下类型准换,向上类型转换是将派生类的指针或引用转换为基类的指针或引用,这是自动进行的并且是安全的,向下类型转换是将基类指针或引用转换为派生类指针,这不会自动进行因为一个基类对于几个派生类,并且如果要转换得加动态类型识别技术用dynamic_cast进行转换。   数组和指针的区别:1、数组在内存中是连续存放的,开辟连续的内存空间;2、使用sizeof(数组)可以计算出数组的字节数,使用sizeof§可以得到指针变量的字节数而不是p所指的内存容量;3、在使用下标的时候数组和指针的用法是相同的,都是原地址加上下标值,不过数组的原地址是数组首地址是固定的,而指针原地址不固定;4、在向函数传递参数时,如果实参是一个数组那么接收的形参就是对应的指针,就是传递过去的数组是首地址而不是整个数组,这会提升效率。

智能指针

  智能指针是什么:智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。动态分配的资源,交给一个类对象去管理,当类对象生命周期结束时,会自动调用析构函数释放资源(使用普通指针会有内存泄漏,就是忘记释放内存或是二次释放的问题),使用智能指针在初始化时要注意,智能指针是一个模板类,可以指定类型,传入指针通过构造函数初始化,也可以使用make_shared初始化,但是不能直接将指针直接赋值给一个智能指针   常用的智能指针有四种:shared_ptr,unique_ptr,weak_ptr,auto_ptr。shared_ptr的实现原理:采用引用计数器的方法,允许多个智能指针指向同一个对象,每当多一个指针指向该对象时,指向该对象的所有智能指针内部的引用计数+1,每当减少一个智能指针指向对象时,引用计数-1,当计数为0的时候会释放动态分配的资源。1、智能指针将一个计数器与类指向的对象关联,引用计数器记录共有多少个类对象共享同一指针;2、每次创建类的新对象时,初始化指针并将引用计数置位1;3、当对象作为另一对象的副本而创建时,拷贝构造函数会拷贝指针并增加与之相应的引用计数;4、对一个对象进行赋值操作时,赋值操作符会减少左操作数所指对象的引用计数(如果减到0就删除对象),并增加右操作数所指对象的引用计数;5、调用析构函数时,构造函数减少引用计数(如果引用计数减至0,就删除基础对象)。shared_ptr实际上维护了两部分信息分别是指向共享资源的指针和引用计数等共享资源的控制信息——维护一个指向控制信息的指针。

{ std::shared_ptr sptr = std::make_shared(200); assert(sptr.use_count() == 1); // 此时引用计数为 1 { std::shared_ptr sptr1 = sptr; assert(sptr.get() == sptr1.get()); assert(sptr.use_count() == 2); // sptr 和 sptr1 共享资源,引用计数为 2 } assert(sptr.use_count() == 1); // sptr1 已经释放 } // use_count 为 0 时自动释放内存

  unique_ptr:采用的是独享所有权语义,一个非空的unique_ptr总是拥有它所指向的资源,转移一个unique_ptr会将所有权全部从源指针转移给目标指针,源指针被置位空;所以unique_ptr不支持普通的拷贝和赋值,不能用在STL容器中;局部变量的返回值除外(因为编译器知道要返回的对象将要被销毁,所以还是能保证独占所有权);如果要拷贝一个unique_ptr那么拷贝结束后,这两个unique_ptr会指向相同的资源,造成在结束时对同一内存指针多次释放而程序崩溃。unique_ptr的生命周期为从unique_ptr指针创建开始,到离开作用域,离开作用域时将其指向的对象销毁,这是基本的RAII思想,在生命周期内可以改变智能指针所指向的对象(创建智能指针时通过构造函数指定,通过reset方法重新指定,通过release方法释放所有权,通过移动语义转移所有权)。使用案例如下:

{ std::unique_ptr uptr = std::make_unique(200); std::unique_ptr uptr1 = uptr; // 编译错误,std::unique_ptr 是 move-only 的 std::unique_ptr uptr2 = std::move(uptr); assert(uptr == nullptr); //也可以指向一个数组 std::unique_ptr uptr = std::make_unique(10); for (int i = 0; i std::cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有