前言:
c++ stl 标准程序库提供了一种智能指针,帮助程序员防止"被异常抛出时发生资源泄露"
本篇只讲述 auto_ptr ,根据 c++ 标准库一书总结
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 也是这样,编译器不会报错,但是程序员要防范
这种错误.
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;
}
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 所以不会发生拥有权的转移