c++ STL(标准程序库) auto_ptr

前言:

c++ stl 标准程序库提供了一种智能指针,帮助程序员防止"被异常抛出时发生资源泄露"
本篇只讲述 auto_ptr ,根据 c++ 标准库一书总结
  • auto_ptr 的设计动机

void f()
{
	classA *p = new classA();
	...
	delete p;
}

如果我们忘记delete p 释放资源那么会造成内存泄露,
就算写了 delete p
如果在函数体内 return 了,那么delete 没执行又泄露了
如果又有异常捕获呢

void f()
{
	classA *p = new classA();
	
	try{
	...
	}
	catch(...){
	delete p;
	throw;
	}
	
	...
	delete p;
}

这才是一个指针p 如果10个呢 那写起来是不是很麻烦,而且还会造成代码的复杂和累赘,
这不是优良的编程风格要尽量避免

如果是智能指针,情形就会大不相同

无论在任何情况下,只要自己被摧毁,就一定连带释放其所指向的资源,auto_ptr 就是这种智能型指针.

#include <memory>
void f()
{
	std::auto_ptr<classA> p(new classA);
}

ok 这样函数就不用担心忘记delete 或者return catch 了
注意一点:
auto_ptr 不允许使用一般指针的赋值方式初始化,不允许隐式转换 explicit

std::auto_ptr<classA> p(new classA); 	//正确
std::auto_ptr<classA> p = new classA; 	//错误
  • auto_ptr 拥有权的转移

auto_ptr 拥有严格的拥有权观念,不能出现多个同时拥有多个对象的状态,
也就是说 一个男人只能取一个老婆,不能同时多个男人同时取一个老婆,
那将会出乱子。auto_ptr 也是这样,编译器不会报错,但是程序员要防范
这种错误.

std::auto_ptr<classA> p(new classA);
std::auto_ptr<classA> p2(p);

这时候 p 就把对象的拥有权交给p2了,这时的p是null 在使用它可能会造成意想不到的后果

std::auto_ptr<classA> p(new classA);
std::auto_ptr<classA> p2;
p2 = p;

赋值和上面的结果一样,p的拥有权交给了p2,通俗讲 p与老婆离婚了,他老婆跟了p2,这时的p也就是光棍null了,没有对象了

如果auto_ptr 以 传值(by value)的方式传递给某函数,那么他的拥有权也交给了函数的形参

void f(std::auto_ptr<classA> t)
{
...
}

std::auto_ptr<classA> p(new classA);
f(p);

// 这时的 p 就是 null 了,在使用就会出现意想不到的问题

你可能认为传引用方式就万事大吉了,然而这种方式更使拥有权捉摸不定,透过引用来获得auto_ptr的函数,你根本无法预知拥有权是否被转移,按引用传递auto_ptr是非常糟糕的设计,要全力避免

考虑到auto_ptr 的概念,我们可以运用 const &
这样的话拥有权就不会发生改变了


void f(const auto_ptr<class A>& p)
{
	....
}

std::auto_ptr <classA> p(new classA);

f(p);

//p还可以使用,他的拥有权还有,const 修饰

如果是函数返回值传递的话,拥有权就转移到函数调用端了

std::auto_ptr<classA> f()
{
	std::auto_ptr<classA> p(new classA);
	...
	return p;
}
  • auto_ptr 的运用实例

在这里插入图片描述

code:

// testSTL_auto_ptr.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


#include <iostream>
#include <memory>

template <class T>
std::ostream& operator<<(std::ostream& stream, const std::auto_ptr<T>& p)
{
	if (p.get() == NULL)
	{
		stream << "NULL";
	}
	else
	{
		stream << *p;
	}
	return stream;
}


int main()
{
	std::auto_ptr<int> p(new int(42));
	std::auto_ptr<int> q;

	std::cout << "after initialization:" << std::endl;
	std::cout << " p:" << p << std::endl;
	std::cout << " q:" << q << std::endl;

	q = p;
	std::cout << "after assigning auto pointers:" << std::endl;
	std::cout << " p:" << p << std::endl;
	std::cout << " q:" << q << std::endl;

	*q += 13;
	p = q;
	std::cout << "after change and reassignment:" << std::endl;
	std::cout << " p:" << p << std::endl;
	std::cout << " q:" << q << std::endl;

	system("pause");
}

运行结果:

after initialization:
 p:42
 q:NULL
after assigning auto pointers:
 p:NULL
 q:42
after change and reassignment:
 p:55
 q:NULL

注意:
std::ostream& operator<<(std::ostream& stream, const std::auto_ptr& p)
这个重载第二个参数是 const reference 所以不会发生拥有权的转移

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章