What's auto_ptr?

  The auto_ptr type is provided by the C++ standard library as a kind of a smart pointer that helps to avoid resource leaks when exceptions are thrown. Note that I wrote "a kind of a smart pointer." There are several useful smart pointer types. This class is smart with respect to only one certain kind of problem. For other kinds of problems, type auto_ptr does not help. So, be careful and read the following subsections.

Why need auto_ptr?

  C++中没有垃圾回收机制,需要程序员动态new和delete,这是不方便并且容易出现内存泄露等等问题的。例如:

  This function is a source of trouble. One obvious problem is that the deletion of the object might be forgotten (especially if you have return statements inside the function). There also is a not-so-obvious danger that an exception might occur. Such an exception would exit the function immediately without calling the delete statement at the end of the function. The result would be a memory leak or, more generally, a resource leak.

  An auto_ptr is a pointer that serves as owner of the object to which it refers (if any).

  这有点类似于Qt的内存处理机制,在Qt中,凡是继承于QObject的类,如果给类的对象指定父类,那么该对象会随着父类的destroyed而destroyed。

  As a result, an object gets destroyed automatically when its auto_ptr gets destroyed. A requirement of an auto_ptr is that its object has only one owner.

How to use auto_ptr?

//header file for auto_ptr
#include <memory> void f()
{
//create and initialize an auto_ptr
std::auto_ptr<ClassA> ptr(new ClassA); ... //perform some operations
}

  when we use auto_ptr, there is no need for delete statement any more.

  An auto_ptr has much the same interface as an ordinary pointer; that is, operator * dereferences the object to which it points, whereas operator -> provides access to a member if the object is a class or a structure.

  However, any pointer arithmetic (such as ++) is not defined (this might be an advantage, because pointer arithmetic is a source of trouble).

  注意:不能使用赋值语句将一个普通指针赋给智能指针auto_ptr<>进行初始化。

 

std::auto_ptr<ClassA> ptr1(new ClassA); //OK
std::auto_ptr<ClassA> ptr2 = new ClassA; //ERROR

  赋予auto_ptr一个新值的方法,新值的类型必须是auto_ptr,而不能是任何普通的指针。

std::auto_ptr<ClassA> ptr;                         //create an auto_ptr
ptr = new ClassA; //ERROR
ptr = std::auto_ptr<ClassA>(new ClassA); //OK, delete old object
// and own new

Transfer of Ownership by auto_ptr

  不要使两个智能指针auto_ptr同时指向同一个对象,这样,该对象会被释放两次,从而产生问题!

  Consider, for example, the following use of the copy constructor:

//initialize an auto_ptr with a new object
std::auto_ptr<ClassA> ptr1(new ClassA);//one //copy the auto_ptr
//- transfers ownership from ptr1 to ptr2
std::auto_ptr<ClassA> ptr2(ptr1); //second

  After the first statement, ptr1 owns the object that was created with the new operator. The second statement transfers ownership from ptr1 to ptr2. So after the second statement, ptr2 owns the object created with new, and ptr1 no longer owns the object. The object created by new ClassA gets deleted exactly once — when ptr2 gets destroyed.

  If ptr2 owned an object before an assignment, delete is called for that object:

//initialize an auto_ptr with a new object
std::auto_ptr<ClassA> ptr1(new ClassA);
//initialize another auto_ptr with a new object
std::auto_ptr<ClassA> ptr2(new ClassA);//own one object already ptr2 = ptr1; //assign the auto_ptr
//- delete object owned by ptr2
//- transfers ownership from ptr1 to ptr2

Source and Sink
所有权的传递暗示着auto_ptr的另外一个用途:函数可以使用auto_ptr来将所有权传递到另一个函数中去。
有两种方式可以发生这种情况!
1.A function can behave as a sink of data. This happens if an auto_ptr is passed as an argument to the function by value(传值). In this case, the parameter of the called function gets ownership of the auto_ptr. Thus, if the function does not transfer it again, the object gets deleted on function exit:
  1. void sink(std::auto_ptr<ClassA>); //sink() gets ownership pass by value.
  2. A function can behave as a source of data. When an auto_ptr is returned, ownership of the returned value gets transferred to the calling function. The following example shows this technique:

std::auto_ptr<ClassA> f()
{
std:: auto_ptr<ClassA> ptr(new ClassA); //ptr owns the new object
...
return ptr; //transfer ownership to calling function
} void g()
{
std::auto_ptr<ClassA> p;
for (int i=; i<; ++i) {
p = f(); //p gets ownership of the returned object
//(previously returned object of f() gets deleted)
...
}
} //last-owned object of p gets deleted

以下情况不要使用auto_ptr

auto_ptr总是包含所有权,因此,在参数表或作为返回值中,如果你不想传递所有权,就不要使用auto_ptr。
如果不恰当地使用auto_ptr,会造成极大的错误,如下例子:
//this is a bad example
template <class T>
void bad_print(std::auto_ptr<T> p) //p gets ownership of passed argument
{
//does p own an object ?
if (p.get() == NULL) {
std::cout << "NULL";
}
else {
std::cout << *p;
}
} //Oops, exiting deletes the object to which p refers
std::auto_ptr<int> p(new int);
*p = ; //change value to which p refers
bad_print (p); //Oops, deletes the memory to which p refers
*p = ; //RUNTIME ERROR

  上面这个例子的意图很简单,就是打印输出参数auto_ptr<T> p的值,但是如果是以pass by value的方式调用函数,那么该函数达到意图的同时,也销毁了p指向的对象,这是极其错误的。因此,我们在使用auto_ptr的时候必须非常谨慎!

  既然以传值(pass by value)的方式不行,那么我们是否可以以传引用(pass by reference)的形式调用函数呢?

  You might think about passing auto_ptrs by reference instead. However, passing auto_ptrs by reference confuses the concept of ownership. A function that gets an auto_ptr by reference might or might not transfer ownership. Allowing an auto_ptr to pass by reference is very bad design and you should always avoid it.

  According to the concept of auto_ptrs, it is possible to transfer ownership into a function by using a constant reference. This is very dangerous because people usually expect that an object won't get modified when you pass it as a constant reference. Fortunately, there was a late design decision that made auto_ptrs less dangerous. By some tricky implementation techniques, transfer of ownership is not possible with constant references. In fact, you can't change the ownership of any constant auto_ptr:

const std::auto_ptr<int> p(new int);
*p = ; //change value to which p refers
bad_print(p); //COMPILE-TIME ERROR
*p = ; //OK

auto_ptrs as Members

  在一个自定义类中使用auto_ptr作为类的成员可以防止资源泄露。如果你使用一个auto_ptr智能指针而不是一个普通指针,那么,你不在需要在类析构函数中delete 该成员。
  除此之外,auto_ptr还有一个很大的作用:一般而言,如果在类的构造函数中抛出异常,便有可能出现资源泄露的可能,
class ClassB {
private:
const std::auto_ptr<ClassA> ptr1; //auto_ptr members
const std::auto_ptr<ClassA> ptr2;
public:
//constructor that initializes the auto_ptrs
//- no resource leak possible
ClassB (ClassA val1, ClassA val2)
: ptr1 (new ClassA(val1)), ptr2(new ClassA(val2)) {
} //copy constructor
//- no resource leak possible
ClassB (const ClassB& x)
: ptr1(new ClassA(*x.ptr1), ptr2(new ClassA(*x.ptr2)) {
} //assignment operator
const ClassB& operator= (const ClassB& x) {
*ptr1 = *x.ptr1;
*ptr2 = *x.ptr2;
return *this;
} //no destructor necessary
//(default destructor lets ptr1 and ptr2 delete their objects)
...
};

 对auto_ptr的误用

  1. auto_ptrs cannot share ownership.

  2. auto_ptrs are not provided for arrays.

  3. auto_ptrs are not "universal smart pointers."

  4. auto_ptrs don't meet the requirements for container elements.

一些例子
#include <iostream>
#include <memory>
using namespace std; /* define output operator for auto_ptr
* - print object value or NULL
*/
template <class T>
ostream& operator<< (ostream& strm, const auto_ptr<T>& p)
{
//does p own an object ?
if (p.get() == NULL) {
strm << "NULL"; //NO: print NULL
}
else {
strm << *p; //YES: print the object
}
return strm;
} int main()
{
auto_ptr<int> p(new int());
auto_ptr<int> q; cout << "after initialization:" << endl;
cout << " p: " << p << endl;
cout << " q: " << q << endl; q = p;
cout << "after assigning auto pointers:" << endl;
cout << " p: " << p << endl;
cout << " q: " << q << endl; *q += ; //change value of the object q owns
p = q;
cout << "after change and reassignment:" << endl;
cout << " p: " << p << endl;
cout << " q: " << q << endl;
}

 

STL之auto_ptr的更多相关文章

  1. stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

    stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...

  2. 【STL】-auto_ptr的用法

    初始化: #include<memory> //auto_ptr header void f() { auto_ptr<classA> ptr(new classA); } 拷 ...

  3. Linux 内核里的“智能指针”【转】

    转自:http://blog.jobbole.com/88279/ 众所周知,C/C++语言本身并不支持垃圾回收机制,虽然语言本身具有极高的灵活性,但是当遇到大型的项目时,繁琐的内存管理往往让人痛苦异 ...

  4. 九章算法:BAT国内班 - 课程大纲

    第1章 国内笔试面试风格及准备方法 --- 分享面试经验,通过例题分析国内面试的风格及准备方法 · 1) C/C++部分: 实现 memcpy 函数 STL 中 vector 的实现原理 · 2)概率 ...

  5. c++11新特性总结(转)

    1.类型与变量相关 1.1.nullptr: 取代了NULL,专用于空指针 1.2.constexpr: 近似const, 可以修饰变量,也可以修饰函数, 修饰变量如: const int globa ...

  6. c++11新特性总结(转。加上重点)

    1.类型与变量相关 1.1.nullptr: 取代了NULL,专用于空指针 1.2.constexpr: 近似const, 可以修饰变量,也可以修饰函数, 修饰变量如: const int globa ...

  7. (转)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现

     转载:http://www.cnblogs.com/felixYeou/archive/2008/08/27/1277250.html 快速导航 一. 回顾历史二. 智能指针简介三. Delphi中 ...

  8. 智能指针(一):STL auto_ptr实现原理

    智能指针实际上是一个类(class),里面封装了一个指针.它的用处是啥呢? 指针与内存 说到指针自然涉及到内存.我们如果是在堆栈(stack)中分配了内存,用完后由系统去负责释放.如果是自定义类型,就 ...

  9. 容器使用的12条军规——《Effective+STL中文版》试读

    容器使用的12条军规——<Effective+STL中文版>试读     还 记的自己早年在学校学习c++的时候,老师根本就没有讲STL,导致了自己后来跟人说 起会C++的时候总是被鄙视, ...

随机推荐

  1. 【转】POJ题目分类

    初级:基本算法:枚举:1753 2965贪心:1328 2109 2586构造:3295模拟:1068 2632 1573 2993 2996 图:最短路径:1860 3259 1062 2253 1 ...

  2. JS响应事件整理

    javascript事件列表解说 事件 浏览器支持 解说 一般事件 onclick IE3.N2 鼠标点击时触发此事件 ondblclick IE4.N4 鼠标双击时触发此事件 onmousedown ...

  3. 封装好的PHP分页类,简单好用--在开源看到的,取回来自己用

    class Pagination  独立分页类 调用方式: $pagenation = new Pagination( 4, 10, 200 ); // 4(第一个参数) = currentPage, ...

  4. matplotlib入门--1(条形图, 直方图, 盒须图, 饼图)

    作图首先要进行数据的输入,matplotlib包只提供作图相关功能,本身并没有数据读入.输出函数,针对各种试验或统计文本数据输入可以使用numpy提供的数据输入函数. # -*- coding: gb ...

  5. CSS3圆角详解

    一.CSS3圆角的优点 传统的圆角生成方案,必须使用多张图片作为背景图案.CSS3的出现,使得我们再也不必浪费时间去制作这些图片了,而且还有其他多个优点: * 减少维护的工作量.图片文件的生成.更新. ...

  6. COS访谈第十八期:陈天奇

    COS访谈第十八期:陈天奇 [COS编辑部按] 受访者:陈天奇      采访者:何通   编辑:王小宁 简介:陈天奇,华盛顿大学计算机系博士生,研究方向为大规模机器学习.他曾获得KDD CUP 20 ...

  7. Weblogic11g+Axis1.4 实现WebService服务

    IDE:NetBeans8.0 项目结构: (1)新建接口Hello.java package com.test; /** * @author y * @date 2015-9-5 7:51:29 * ...

  8. FLASK初步实践

    感觉经过DJANGO,CI,RAILS之类的WEB框架之后,FLASK的思路就比较顺畅了... FLASKR.PY import sqlite3 from flask import Flask, re ...

  9. 【Java解惑】表达式问题

    1. 如果判断一个参数是否是奇数? 我们通过下面代码来尝试一下,看看方法可行不: public static boolean isOdd(int i) { return i % 2 == 1; } p ...

  10. 元素水平垂直居中(transform,margin,table-cell,jQuery)

    1.水平居中 .div{ margin:0 auto; (或者 margin:auto;) width:500px; height:300px; } 2.使用margin水平垂直居中 方式一: .di ...