智能指针auto_ptr详解

概述:C++中有很多种智能指针,auto_ptr就是其中的一种,该智能指针主要是为了解决“因程序异常退出发生的内存泄漏”这类问题的。

我们先来看下面的问题代码

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

//一般指针的处理方式
template<typename T>
class OldClass
{
public:
	OldClass(T a)
	{
		ptr = new T(a);
	}
	~OldClass()
	{
		delete ptr;
	}
private:
	T * ptr;
};
int main()
{
	OldClass<int> a(2);
	int * p = new int(1);
	throw runtime_error("1");//程序发生异常退出
	delete p;
}

在上面的例子中类OldClass中在构造函数中为成员指针开辟内存资源,在析构函数中释放内存资源;现在如果在main主函数中发生异常即throw runtime_error("1");导致程序退出;则该程序将会造成严重影响,即:一、main函数中的指针p未被释放;二、由于程序的异常结束将类对象a的析构函数也将不会被调用,即对象a自身的内存资源也没有被释放。这两种情况都将会造成内存泄漏。

常规的解决办法就是利用异常处理来解决,具体修改代码如下:

int main()
{
	OldClass<int> a(2);
	try
	{
	int * p = new int(1);
	//发生异常退出
	try
	{
		throw runtime_error("1");
	}
	catch(exception ex)
	{
		delete p;//必须针对每一个可能因异常而未释放资源的指针先进行释放处理
		throw ex;//再继续将原异常抛出
	}
	delete p;

	}
	catch(runtime_error ex)
	{
		cerr<<ex.what()<<endl;
		//此处进行异常处理
	}
}

即必须针对每一个可能因为异常而无法释放的指针在异常传递的中间先释放该指针后再继续原异常抛出,可见这种办法很为复杂,因为必须为每一个指针都进行类似的处理。

智能指针的出现:为了方便解决该问题的首段之一就是智能指针,即可以将任何一种类型(包括自定义类型)转换成自能指针,转换成智能指针后由于智能指针本身就是区域变量,所以无论程序是正常退出还是异常退出,只要程序退出时则智能指针都会被自动销毁释放内存资源。

下面对智能指针的常见用法和注意点做几点详细介绍:

一、智能指针的初始化时,只能用一个智能指针给另一个智能指针初始化,普通指针则不能。

<span style="white-space:pre">	</span>auto_ptr<int> a = auto_ptr<int>(new int(2));
	int *p = new int(1);
	//auto_ptr<int> b = p;//报错
	auto_ptr<int> c(p);
	cout<<*a<<endl;
	cout<<*c<<endl;

	/*
	输出结果:
	2
    <span style="white-space:pre">	</span>1
    <span style="white-space:pre">	</span>请按任意键继续. . .
	*/

二、每一个智能指针都是它所指向的对象的拥有者,且每一个对象都只能有一个拥有者,所以智能指针的构造函数和赋值操作原理上都是拥有权ownership的转移

	auto_ptr<int> a = auto_ptr<int>(new int(2));
	auto_ptr<int> c = auto_ptr<int>(new int(1));
	//a将值为2的对象的拥有权转移给c,a变成一个null指针
	//c将值为1的对象销毁并交出拥有权后接受a转移的拥有权
	c = a;
	//c将拥有权转移给d,自己变成null指针
	auto_ptr<int> d(c);

三、智能指针和一般指针的用法一致,都含有operate*和operate->操作,但是智能指针却不能进行任何算术运算,这是由于智能指针拥有权的特性决定的。

四、智能指针做为函数的参数类型或返回值类型时都会发生对象拥有权的转移,如果将函数外部对象的拥有权转移进入函数内,而不再用返回值将其拥有权转移出来的话,则该外部对象将会随着函数调用的结束会被销毁,这是很可怕的事情所以要慎用。

五、在函数间传递智能指针时最安全的方式是用常量引用constant reference,这样外部对象的拥有权不会被转移到函数内部的局部变量中,当然这样的对象转递进去后是不能修改的,不能赋值给别的对象或被别的对象给赋值;也你建议用引用reference去传递智能指针对象,因为这样很容易造成拥有权的混淆。

	auto_ptr<int> a = auto_ptr<int>(new int(2));
	auto_ptr<int> c = auto_ptr<int>(new int(1));
	const auto_ptr<int> & d = c;
	cout<<*a<<endl;
	cout<<*c<<endl;
	cout<<*d<<endl;
	//输出2、1、1
	//a = d;编译报错

值得加以说明的是:对于auto_ptr对象的constant reference与一般的对象的常量引用有所不同,对于auto_ptr智能指针对象const并非意味着你不能更改该指针所拥有的对象,而是意味着你不能更改auto_ptr的拥有权。

六、不村子针对数组array的智能指针,因为auto_ptr是透过delete操作而非delete[]操作来销毁对象的。

七、智能指针对象不能做为标准容器的元素,因为标准容器中最基本的复制和拷贝操作都会使原有的auto_ptr对象交出拥有权,而不是拷贝给新的对象。

下面附上智能指针运用完整例子:

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

//智能指针处理
template<typename T>
class NewClass
{
public:
	NewClass(T a)
	{
		ptr = auto_ptr<T>(new T(a));
	}
	NewClass(const NewClass<T> &nc):ptr(new T(nc.Get())){}

	~NewClass(){}
	T Get(){return *ptr;}
	void Set(T t){*ptr = t;}
private:
	auto_ptr<T> ptr;
};

template<typename T>
void fun(const auto_ptr<T> & ap)
{
	//该函数的功能是将指针所指对象中的数据成员加陪
	ap->Set((*ap).Get()*2);
}

int main()
{
	//建立NewClass对象的智能指针
	auto_ptr<NewClass<int>> a(new NewClass<int>(2));
	cout<<a->Get()<<endl;
	//将a中的数据加倍
	fun(a);
	cout<<a->Get()<<endl;

	/*
	2
	4
	请按任意键继续. . .
	*/
}

最后简单小结一下:其实aoto_ptr智能指针确实还是挺方便的,只是自己在运用的时候多注意对象拥有者的唯一性,不要轻易的进行指针间的赋值或传值就可以了。

智能指针auto_ptr详解,布布扣,bubuko.com

时间: 2024-12-28 18:17:07

智能指针auto_ptr详解的相关文章

C++ 智能指针auto_ptr详解

1. auto_ptr 的设计动机: 函数操作经常依照下列模式进行: 获取一些资源 执行一些动作 释放所获取的资源 那么面对这些资源的释放问题就会出现下面的两种情况: 一开始获得的资源被绑定于局部对象,那么当函数退出的时候,这些局部对象的析构函数被自动的调用,从而自动释放掉这些资源; 一开始获得的资源是通过某种显示手段获取,而且并没有绑定在任何对象身上,那么必须以显式的方式释放.这种情况常常发生在指针身上; 例子: 1 void f() 2 { 3 ClassA* ptr = new Class

C++智能指针用法详解

一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见. 用智能指针便可以有效缓解这类问题,本文主要讲解参见的智能指针的用法.包括:std::auto_ptr.boost::scoped_ptr.boost::shared_ptr.boost::scoped_array.boost::shared_array.boost:

C++11 shared_ptr(智能指针)详解

要确保用 new 动态分配的内存空间在程序的各条执行路径都能被释放是一件麻烦的事情.C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared _ptr 模板,就是用来部分解决这个问题的. 只要将 new 运算符返回的指针 p 交给一个 shared_ptr 对象“托管”,就不必担心在哪里写delete p语句——实际上根本不需要编写这条语句,托管 p 的 shared_ptr 对象在消亡时会自动执行delete p.而且,该 shared_ptr 对象能像指针 p —

C++中的智能指针(auto_ptr)

实际上auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是完全完美的. 本文从下面的8个方面来总结auto_ptr使用的大部分内容. 1. auto_ptr是什么? auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个这样拥有者(auto_ptr).当auto_ptr对象生命

C++:浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析,左值与右值

C++:浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析 by 小威威 1. 知识引入 在C++编程中,动态分配的内存在使用完毕之后一般都要delete(释放),否则就会造成内存泄漏,导致不必要的后果.虽然大多数初学者都会有这样的意识,但是有些却不以为意.我曾问我的同学关于动态内存的分配与释放,他的回答是:"只要保证new和delete成对出现就行了.如果在构造函数中new(动态分配内存),那么在析构函数中delete(释放)就可以避免内存泄漏了!" 事实果真如此么?

【C++智能指针 auto_ptr】

<More Effective C++>ITEM M9中提到了auto_ptr,说是当异常产生的时候,怎么释放为对象分配的堆内存,避免重复编写内存释放语句. PS:这里书里面提到函数退出问题,函数退出会清理栈内存,不管是怎么正常退出还是异常退出(仅有一种例外就是当你调用 longjmp 时.Longjmp 的这个缺点是 C++率先支持异常处理的主要原因).建立在此基础上我们才把对指针的删除操作封装到一个栈对象里面.这样函数退出(异常或是正常)就会调用对象的析构函数,达到我们自动清理所封装指针指

C++智能指针 auto_ptr

C++智能指针 auto_ptr auto_ptr 是一个轻量级的智能指针, 定义于 memory (非memory.h)中, 命名空间为 std. auto_ptr 适合用来管理生命周期比较短或者不会被远距离传递的动态对象, 最好是局限于某个函数内部或者是某个类的内部. 使用方法: std::auto_ptr<int> pt(new int(10)); pt.reset(new int(11)); 成员函数 3个重要的函数: (1) get 获得内部对象的指针, 由于已经重载了()方法, 因

C语言指针传递详解

传递指针可以让多个函数访问指针所引用的对象,而不用把对象声明为全局可访问,要在某个函数中修改数据,需要用指针传递数据,当数据是需要修改的指针的时候,就要传递指针的指针,传递参数(包括指针)的时候,传递的是它们的值,也就是说,传递给函数的是参数值的一个副本 本文将讨论C语言中指针传递给函数与从函数返回指针 本文地址:http://www.cnblogs.com/archimedes/p/c-transfer-point.html,转载请注明源地址. 用指针传递数据 用指针传递数据的一个主要原因是函

C++智能指针--auto_ptr指针

auto_ptr是C++标准库提供的类模板,头文件<memory>,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者.当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放.即使发生异常,通过异常的栈展开过程也能将动态内存释放.auto_ptr不支持new数组. auto_ptr的出现,主要是为了解决"有异常抛出时发生内存泄漏"的问题.如下的简单代码是这类问题的一个简单示