指针如何初始化_C++ Boost 智能指针详解

本文介绍了C++ Boost库中的智能指针,包括作用域指针、作用域数组、共享指针、共享数组、弱指针和介入式指针,强调了它们在内存管理中的优势,如自动释放和防止内存泄漏。通过示例和源码分析,阐述了各种智能指针的使用和工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(给CPP开发者加星标,提升C/C++技能)

来源:造轮子https://blog.youkuaiyun.com/Marble_ccp/article/details/105606236
前言

学习过C/C++的同学都知道,有一个非常方便又特别让人烦的数据类型,那就是指针,不仅操作麻烦,还有各种“级别”,一级指针、二级指针、n级别指针…很多人从入门到放弃C/C++,很大一个原因是因为搞不清楚指针、以及指针与其他对象之间千丝万缕的关系。而在实际的开发过程中,经常会出现因为未释放申请的对象而导致内存溢出、程序奔溃。这里就包括指针对象的释放,那如果有一种指针,能申请对象后“自动”释放,是不是很爽?本文将介绍Boost中提到的各种智能指针。

C++中出现智能是在1998年修订的第一版C++标准中:std::auto_ptr 。与下面boost中的其他智能指针相比,它就像是个普通的指针:通过地址来访问一个动态分配的对象。它会在析构时调用 delete 操作符来自动释放所包含的对象。前提是在初始化的时候,传给它一个由 new 操作符返回的对象地址。这就明显减少了程序员手动delete的繁琐操作。

另一方便,程序中频繁出现的“异常”,也可以导致未正确释放内存,而出现内存泄漏。而智能指针,可以在析构函数中准确释放内存,避免出现内存泄漏。这也是智能指针的优点之一。Boost C++ 库 Smart Pointers 提供了许多可以用在各种场合的智能指针。

你知道RAII吗?

习语 RAII(Resource Acquisition Is Initialization) :资源申请即初始化。智能指针是该习语重要的实现之一。智能指针确保在任何情况下,动态分配的内存都能得到正确释放,从而将开发人员从这项任务中解放出来。这包括程序因为异常而中断,原本用于释放内存的代码被跳过的场景。用一个动态分配的对象的地址来初始化智能指针,在析构的时候释放内存,就确保了这一点。因为析构函数总是会被执行的,这样所包含的内存也将总是会被释放。

无论何时,一定得有第二条指令来释放之前另一条指令所分配的资源时,RAII 都是适用的。许多的 C++ 应用程序都需要动态管理内存,因而智能指针是一种很重要的 RAII 类型。不过 RAII 本身是适用于许多其它场景的。

基于上述描述,如下代码片段,模拟智能指针实现。

// Smart_ptr.hpp#include using namespace std;template<class T>class Smart_ptr{
    public:  Smart_ptr(T *t)  {
        cout << "Smart_ptr 构造函数" << endl;    this->t = t;  }  ~Smart_ptr()  {
        if (this->t != NULL)    {
          cout << "Smart_ptr 西沟函数" << endl;      delete this->t;    }  }  T* &operator->()  {
        return this->t;  }private:  T *t;};

构造Person测试类

#include #include using namespace std;class Person{
    public:  Person(std::string name, int age) :name(name), age(age){
        cout << "Person 的构造函数" << endl;  }  Person(){
        cout << "Person 的默认构造" << endl;  }  void operator=(const Person& p){
        this->age = p.age;    this->name = p.name;  }  ~Person(){
        cout << "Person 的析构函数" << endl;  }  void Show(){
        cout << this->name << "小朋友今年" << this->age << "岁了" << endl;  }private:  std::string name;  int age;};

测试代码

#include"Smart_ptr.hpp"#include"Person.hpp"int main(){    Smart_ptr p = Smart_ptr(new Person("小花", 22));  p->Show();  return 0;}

运行结果0b3ba05ba885492c0824807e690fe5be.png从测试代码中看出,我new了Person对象,在程序结束时并没有delete,但是却打印出了调用析构函数的日志【不信你可以断点调试这个程序,O(∩_∩)O哈哈~】。这就说明智能指针已经起作用了,帮你省掉了delete的步骤。是不是很开心^-^。

上述只是简单地引入了一下智能指针的概念,以及描述了智能指针的作用,下面将着重介绍boost库中提供的强大的智能指针。

3、作用域指针
3.1、概述

作用域指针类名为: boost::scoped_ptr。一个作用域指针独占一个动态分配的对象。它的定义在 boost/scoped_ptr.hpp 中。不像 std::auto_ptr,一个作用域指针不能传递它所包含的对象到另一个作用域指针,也就是说无法通过拷贝构造传参。一旦用一个地址来初始化,这个动态分配的对象将在析构阶段释放。

一个作用域指针只独占一个内存地址,所以  boost::scoped_ptr 的实现就要比 std::auto_ptr 简单。在不需要拷贝构造传递的时候应该优先使用 boost::scoped_ptr 。

3.2、如何使用scoped_ptr

下面代码片段,演示如何调用 boost::scoped_ptr。其中Person对象贯穿全篇,定义在本文开头处。

int main(){
      boost::scoped_ptr p(new Person("小红", 12));  p->Show();   // 等价于 p.get()->Show();   //boost::scoped_ptr p1(p);;  // 无法使用scoped_ptr拷贝构造定义初始化另一个对象  return 0;}

执行结果8474195426c1dbdbceb4eb3ddbbeb743.png

一经初始化,智能指针  boost::scoped_ptr 所包含的对象,可以通过类似于普通指针的接口来访问。这是因为重载了相关的操作符,operator->() 和 operator bool() 。此外,还有 get() 和 reset() 方法。前者返回所含对象的地址,后者用一个新的对象来重新初始化智能指针。在这种情况下,新创建的对象赋值之前会先自动释放所包含的对象。

boost::scoped_ptr 的析构函数中使用 delete 操作符来释放所包含的对象。这对 boost::scoped_ptr 所包含的类型加上了一条重要的限制。即boost::scoped_ptr 不能用动态分配的数组来做初始化,因为这需要调用 delete[] 来释放。在这种情况下,可以使用下面将要介绍的 boost:scoped_array 类。

3.3、scoped_ptr源码分析

如下代码片段是截取的boost::scoped_ptr源码核心部分,相关解释见注释。

// scoped_ptr.hpp#include #include #include #include #include #include #include #ifndef BOOST_NO_AUTO_PTR# include           // for std::auto_ptr#endifnamespace boost{
    //  scoped_ptr mimics a built-in pointer except that it guarantees deletion//  of the object pointed to, either on destruction of the scoped_ptr or via//  an explicit reset(). scoped_ptr is a simple solution for s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值