C++如何用智能指针管理内存资源

1.简介

C++作为一门应用广泛的高级编程语言,却没有像Java、C#等语言拥有垃圾回收(Garbage Collection )机制来自动进行内存管理,这也是C++一直被诟病的一点。C++在发展的过程中,一直致力于解决内存泄漏,C++虽然基于效率的考虑,没有采用垃圾回收机制,但从C++98开始,推出了智能指针(Smart Pointer)来管理内存资源,以弥补C++在内存管理上的技术空白。

智能指针是C++程序员们一件管理内存的利器,使用智能指针管理内存资源,实际上就是将申请的内存资源交由智能指针来管理,是RAII技术的一种实现。RAII是C++的之父Bjarne Stroustrup教授提出的概念,RAII全称是“Resource Acquisition is Initialization”,直译过来是“资源获取即初始化”,也就是说在构造函数中获取资源,在析构函数中释放资源。因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在RAII的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。

“资源获取即初始化”,在使用智能指针管理内存资源时,“资源”指的是通过new或malloc申请的内存资源,“初始化”指的是使用申请的内存资源来初始化栈上的智能指针类对象。使用智能指针管理内存资源的好处显而易见,通过智能指针对象在声明周期结束时,自动调用析构函数,在析构函数中完成对内存资源的释放,即自动的调用内存资源的释放代码,避免因忘记对内存资源的释放导致内存泄漏。

2.实例

下面看一个使用由C++11引入的智能指针unique_ptr来管理内存资源的例子。

#include <memory>
#include <iostream>
using namespace std;

class A
{
public:
	A() {}
	~A()
	{
		cout<<"A's destructor"<<endl;
	}
	void Hello()
	{
		cout<<"use smart pointer to manage memory resources as far as possible"<<endl;
	}
};

int main()
{
	unique_ptr<A> pA(new A);
	pA->Hello();
	return 0;
}

程序输出:

use smart pointer to manage memory resources as far as possible
A's destructor

可见在main()函数结束后,类A的析构函数被自动调用,完成了内存资源了释放。

在创建智能指针对象时,也可以暂时不指定内存资源,先创建一个空的智能指针对象。空智能指针对象不可以进行任何操作,但可以使用 get() 成员函数来判断是否存在内存资源,如果为空则可以指定内存资源。类似于如下操作:

unique_ptr<int> pInt;
if (pInt.get()==nullptr)
{
	pInt.reset(new int(8));
	cout<<*pInt<<endl;
}

使用 unique_ptr 智能指针来管理内存资源时,是对内存资源的独占式管理,即内存资源的所有权不能进行共享,同一时刻只能有一个 unique_ptr 对象占有某个内存资源。如果发生赋值或拷贝构造,则会在编译期报错,因为unique_ptr禁止了拷贝语义,提高了代码的安全性。

unique_ptr<int> pInt(new int(8));
unique_ptr<int> pInt1=pInt;	//编译报错
unique_ptr<int> pInt2(pInt);	//编译报错

当然,可以通过移动语义完成内存资源的所有权转移,转移之后,原智能指针对象变为空智能指针对象,不能再对内存资源进行任何操作,否则会发生运行时错误,但我们也可以使用get()成员函数进行判空处理。

unique_ptr<int> pInt(new int(8));
unique_ptr<int> pInt1=std::move(pInt);		//转移所有权
*pInt=6;																//对空智能指针进行赋值操作将报运行时错误
if(!pInt.get())														//判空处理更安全
{
	*pInt=6;
}

独占式的内存资源管理可以使用 unique_ptr 来完成,但是如果想对内存资源进行共享式管理,那么 unique_ptr 就无能为力了。shared_prt 使用引用计数来实现对内存资源的共享式管理,当对内存资源的引用计数变为0时,由最后一个对内存资源拥有管理权的智能指针对象完成对内存资源的释放。

#include <memory>
#include <iostream>
using namespace std;

class A
{
public:
	A() {}
	~A()
	{
		cout << "A's destructor" << endl;
	}
	void Hello()
	{
		cout << "use smart pointer to manage memory resources as far as possible" << endl;
	}
};

int main()
{
	shared_ptr<A> spInt(new A);		//接管内存资源
	cout << "reference count "<<spInt.use_count() << endl;
	shared_ptr<A> spInt1 = spInt;	//spInt1获取内存资源的管理权
	spInt1->Hello();
	cout << "reference count " << spInt.use_count() << endl;
	spInt1.reset();						//spInt1放弃对内存资源的管理权
	cout << "reference count " << spInt.use_count() << endl;
}

程序编译运行结果:

reference count 1
use smart pointer to manage memory resources as far as possible
reference count 2
reference count 1
A's destructor

3.智能指针使用注意事项

智能指针虽然增强了安全性,避免了潜在的内存泄漏,但是我们在使用时还是应该遵守一定的规则,以保证代码的健壮性。
(1)smart_ptr<T> 不等于 T*,使用时不能完全按照T*来使用。因为smart_ptr<T>本质上是类对象,一个用于管理内存资源的智能指针类对象,而T*是一个指向类型T的指针,二者不能随意地转换和赋值;

(2)使用独立的语句将newed对象置入智能指针,因为使用临时智能指针对象可能会引发内存泄漏。比如下面的语句:

process(shared_ptr<A>(new A),foo());

实际上对 process() 函数调用时编译器需要完成如下三步为process()准备好实参。

(1)调用函数foo();
(2)执行new A表达式;
(3)调用shared_ptr<A>构造函数,初始化智能指针对象。

实际上,不同的编译器在执行上述三个语句时可能会有不同的顺序,如果编译器将(2.2)放在(2.1)之前执行,执行顺序如下:

(1)执行new A表达式;
(2)调用函数foo();
(3)调用shared_ptr<A>构造函数,初始化智能指针对象。

如果在调用函数foo()时抛出异常,那么new A表达式产生的指向堆对象指针将会丢失,于是产生了内存泄漏。解决办法就是使用独立的语句将newed对象置入智能指针,做法如下:

shared_ptr<A> spA(new A);
process(spA,foo());

以上就是C++如何用智能指针管理内存资源的详细内容,更多关于c++ 智能指针管理内存的资料请关注我们其它相关文章!

(0)

相关推荐

  • c++11 新特性——智能指针使用详解

    c++11添加了新的智能指针,unique_ptr.shared_ptr和weak_ptr,同时也将auto_ptr置为废弃(deprecated). 但是在实际的使用过程中,很多人都会有这样的问题: 不知道三种智能指针的具体使用场景 无脑只使用shared_ptr 认为应该禁用raw pointer(裸指针,即Widget*这种形式),全部使用智能指针 初始化方法 class A { public: A(int size){ this->size = size; } A(){} void Sh

  • c++11&14-智能指针要点汇总

    学c++的人都知道,在c++里面有一个痛点,就是动态内存的管理,就我所经历的一些问题来看,很多莫名其妙的问题,最后都发现是内存管理不当引起的. 但像java等其他一些语言则不会有这样的问题,为什么呢,因为它们有很好的处理内存的方法,比如java的垃圾回收机制,现在,我们c++终于也有了智能指针. 1. 什么是智能指针 简单地说,智能指针是用对象去管理一个资源指针,同时用一个计数器计算引用当前指针对象的个数,当管理指针的对象增加或减少时,计数器也相应加1或减1,当最后一个指针管理对象销毁时,计数器

  • C++11智能指针之weak_ptr详解

    如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以看看另一篇文章: [C++11新特性] C++11智能指针之shared_ptr 1.为什么需要weak_ptr? 在正式介绍weak_ptr之前,我们先来回忆一下shared_ptr的一些知识. 我们知道shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个动态对

  • C++ 中boost::share_ptr智能指针的使用方法

    C++ 中boost::share_ptr智能指针的使用方法 最近项目中使用boost库的智能指针,感觉智能指针还是蛮强大的,在此贴出自己学习过程中编写的测试代码,以供其他想了解boost智能指针的朋友参考,有讲得不正确之处欢迎指出讨论.当然,使用boost智能指针首先要编译boost库,具体方法可以网上查询,在此不再赘述. 智能指针能够使C++的开发简单化,主要是它能够自动管理内存的释放,而且能够做更多的事情,即使用智能指针,则可以再代码中new了之后不用delete,智能指针自己会帮助你管理

  • C++11智能指针中的 unique_ptr实例详解

    在前面一篇文章中,我们了解了 C++11 中引入的智能指针之一 shared_ptr 和 weak_ptr ,今天,我们来介绍一下另一种智能指针 unique_ptr . 往期文章参考: [C++11新特性] C++11 智能指针之shared_ptr [C++11新特性] C++11智能指针之weak_ptr unique_ptr介绍 unique是独特的.唯一的意思,故名思议,unique_ptr可以"独占"地拥有它所指向的对象,它提供一种严格意义上的所有权. 这一点和我们前面介绍

  • 详解C++-(=)赋值操作符、智能指针编写

    (=)赋值操作符 编译器为每个类默认重载了(=)赋值操作符 默认的(=)赋值操作符仅完成浅拷贝 默认的赋值操作符和默认的拷贝构造函数有相同的存在意义 (=)赋值操作符注意事项 首先要判断两个操作数是否相等 返回值一定是 return *this; 返回类型是Type&型,避免连续使用=后,出现bug 比如: class Test{ int *p; Test(int i) { p=new int(i); } Test& operator = (const Test& obj) { i

  • C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)

    shared_ptr基本用法 shared_ptr采用引用计数的方式管理所指向的对象.当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1.当shared_ptr离开作用域时,引用计数减1.当引用计数为0时,释放所管理的内存. 这样做的好处在于解放了程序员手动释放内存的压力.之前,为了处理程序中的异常情况,往往需要将指针手动封装到类中,通过析构函数来释放动态分配的内存:现在这一过程就可以交给shared_ptr去做了. 一般我们使用make_shared来

  • C++11 智能指针之shared_ptr代码详解

    C++中的智能指针首先出现在"准"标准库boost中. 随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象. 在新标准中,主要提供了shared_ptr.unique_ptr.weak_ptr三种不同类型的智能指针. 接下来的几篇文章,我们就来总结一下这些智能指针的使用. 今天,我们先来看看shared_ptr智能指针. shared_ptr 智能指针 shared_ptr是一个引用计数智能指针,用于共享对象的所有权也就是说它允许

  • C++如何用智能指针管理内存资源

    1.简介 C++作为一门应用广泛的高级编程语言,却没有像Java.C#等语言拥有垃圾回收(Garbage Collection )机制来自动进行内存管理,这也是C++一直被诟病的一点.C++在发展的过程中,一直致力于解决内存泄漏,C++虽然基于效率的考虑,没有采用垃圾回收机制,但从C++98开始,推出了智能指针(Smart Pointer)来管理内存资源,以弥补C++在内存管理上的技术空白. 智能指针是C++程序员们一件管理内存的利器,使用智能指针管理内存资源,实际上就是将申请的内存资源交由智能

  • 融会贯通C++智能指针教程

    目录 一.基础知识介绍 裸指针常出现以下几个问题: 二.不带引用计数的智能指针 不带引用计数的智能指针主要包括 (1)auto_ptr源码 (2)scoped_ptr (3)unique_ptr源码 三.带引用计数的智能指针 四.shared_ptr 和 weak_ptr 智能指针的交叉引用问题 五.多线程访问共享对象的线程安全问题 六.自定义删除器 一.基础知识介绍 裸指针常出现以下几个问题: 忘记释放资源,导致资源泄露(常发生内存泄漏问题) 同一资源释放多次,导致释放野指针,程序崩溃 写了释

  • C++智能指针之shared_ptr的具体使用

    目录 std::shared_ptr概念 shared_ptr模板类 shared_ptr的构造和析构 shared_ptr赋值 make_shared 计数线程安全? enable_shared_from_this shared_ptr使用注意事项: 总结 std::shared_ptr概念 unique_ptr因为其局限性(独享所有权),一般很少用于多线程操作.在多线程操作的时候,既可以共享资源,又可以自动释放资源,这就引入了shared_ptr. shared_ptr为了支持跨线程访问,其

  • c++ 智能指针基础详解

    简介 在现代 C++ 编程中,标准库包含了智能指针(Smart pointers). 智能指针用来确保程序不会出现内存和资源的泄漏,并且是"异常安全"(exception-safe)的. 智能指针的使用 智能指针定义在头文件 memory 里的命名空间 std 中.它对于资源获取即初始化(RAII, Resource Acquisition Is Initialization) 编程理念至关重要.该理念的目的是保证对象初始化的时候也是资源获取的时候,从而使对象的所有资源在单行代码中创建

  • 深入学习C++智能指针之shared_ptr与右值引用的方法

    目录 1. 介绍 2. 初始化方法 2.1 通过构造函数初始化 2.2 通过拷贝和移动构造函数初始化 2.3 通过 std::make_shared 初始化 2.4 通过 reset 方法初始化 3. 获取原始指针 4. 指定删除器 5. 参考链接 1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用

  • 一文掌握C++ 智能指针全部用法

    目录 一.为什么要使用智能指针 二.auto_ptr 三.unique_ptr 四.shared_ptr 五.weak_ptr 六.智能指针的使用陷阱 七.总结 为什么要学习智能指针? 咳咳,这个问题不是问大家的,是询问我自己的! 我依稀记得刚离校出来找实习工作那会,去面试一份工作,其中有一个环节需要答题:有一道题目就是问什么是智能指针?卧槽?当时我就懵逼,智能指针我压根就没有听说过- 最后,面试的这份工作理所应当的黄了. 差不多是一年前左右吧,现在趁有闲余时间,学习一下智能指针,丰富一下自己!

  • C++11 智能指针的具体使用

    目录 智能指针的原理 RAII 智能指针的原理 auto_ptr 1.auto_ptr的使用及问题 unique_ptr shared_ptr shared_ptr的循环引用 智能指针的原理 RAII RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存.文件句柄.网络连接.互斥量等等)的简单技术. 在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源. 借此,我

  • C++11中的智能指针shared_ptr、weak_ptr源码解析

    目录 1.前言 2.源码准备 3.智能指针概念 4.源码解析 4.1.shared_ptr解析 4.1.1.shared_ptr 4.1.2.__shared_ptr 4.1.3.__shared_count 4.1.4._Sp_counted_base 4.1.5._Sp_counted_ptr 4.1.6.shared_ptr总结 4.2.weak_ptr解析 4.2.1.weak_ptr 4.2.2.__weak_ptr 4.2.3.__weak_count 4.2.4.回过头看weak_

  • C++Smart Pointer 智能指针详解

    目录 一.为啥使用智能指针呢 二.shared_ptr智能指针 三.unique_ptr智能指针 四.weak_ptr智能指针 五.智能指针怎么解决交叉引用,造成的内存泄漏 5.1交叉引用的栗子: 5.2解决方案 六.智能指针的注意事项 总结 一.为啥使用智能指针呢 标准库中的智能指针: std::auto_ptr --single ownership (C++98中出现,缺陷较多,被摒弃) std::unique_ptr --single ownership (C++11替代std::auto

随机推荐