Class auto_ptr

C++標準程序庫提供的auto_ptr是一種智能型指針,幫助程序員防止「被異常拋出時發生資源泄漏」。注意我說的是「一種」智能型指針,現實生活中還有其餘許多有用的智能型指針,auto_ptr只是針對某個特定問題而設計的,對於其餘問題,auto-ptr無能爲力。ios

1、auto_ptr的設計動機:
函數的操做常常須要依如下模式進行:
一、獲取一些資源。
二、執行一些操做。
三、釋放所得到的資源。
     假如函數一開始得到的資源被綁定在局部對象身上,當函數退出時,他們的析構函數被調用,從而自動釋放這些資源。可是若是函數一開始得到的資源是以顯式手法(好比說:new)得到,那就必須以顯示手法(好比說:delete)釋放。可是有時候會忘記delete或者異常一旦發生,函數馬上退出,根本執行不到函數尾端的delete語句,這就可能形成內存泄漏。固然你能夠在函數中實現捕捉全部異常。但會使得函數變得十分複雜且容易出錯。
    若是使用智能型指針能保證在任何一種狀況下,只要本身被摧毀,就必定連帶釋放其所指的資源(由於智能型指針原本就是局部變量,因此不管是正常退出,仍是異常退出,都能保證該指針被銷燬從而釋放資源)。程序員

注意點:
    一、auto_ptr是這樣一種指針:他是「他所指向的對象」的擁有者。因此,當身爲對象擁有者的auto_ptr被摧毀時,該對象也將遭到摧毀。auto_ptr要求一個對象只能有一個擁有者。再也不須要delete,也再也不須要catch。
    二、auto_ptr擁有權是能夠轉移的:函數

std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2(ptr1);
或者
std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2;
ptr2 = ptr1;

在第一個語句中,ptr1擁有了那個new出來的對象。在 第二個語句中,擁有權由ptr1轉交給ptr2。此後ptr2即擁有了那個new出來的對象,而ptr1不在擁有他。這樣,對象就只會被delete一次(在ptr2被摧毀時)。
    若是ptr2在轉交擁有權以前擁有另外一個對象,則轉交操做執行以前會先調用delete,將ptr2所擁有的對象先摧毀。spa

std::auto_ptr<ClassA> ptr1(new ClassA);
std::auto_ptr<ClassA> ptr2(new ClassA);
ptr2 = ptr1; //ptr2以前擁有的對象被銷燬,ptr1將第一個new出來的對象的擁有權轉交給ptr2,ptr1爲NULL。

    特殊用法:某個函數能夠利用auto_ptr將擁有權轉交給另外一個函數。這種狀況可能出如今兩種狀況:
        a、auto_ptr被以傳值的方式被看成一個參數傳遞給某個函數。此時被調用函數的參數就得到了這個auto_ptr的擁有權。設計

void sink(std::auto_ptr<ClassA>);

    b、當auto_ptr被看成返回值返回時,將擁有權轉交給調用端。指針

std::auto_ptr<ClassA> fun()
{
    std::auto_ptr<ClassA> ptr(new ClassA);
    ...
    return ptr;
}

void gun()
{
    std::auto_ptr<ClassA> ptr;
    for (int i=0; i<10; i++)
    {
        p = fun(); //一旦進入循環再次執行賦值動做,意味着ptr先前擁有的對象被銷燬了。
        ...
    }
}

三、const std::auto_ptr<class T> ptr;ptr的擁有權不容許被轉移。在這裏,關鍵詞const並不是意味着你不能更改auto_ptr所擁有的對象,而是意味着你不能更改auto_ptr的擁有權。例如:code

std::auto_ptr<int> f()
{
    const auto_ptr<int> p(new int);
    auto_ptr<int> q(new int);
    *p = 42;    //ok
    q = p;      //error
    p = q;      //error
    return p;   //error
}

四、並不存在針對array設計的auto_ptr。由於auto_ptr是透過delete而非delete[]來釋放其所擁有的對象。
五、auto_ptr不知足STL標準容器的對其元素的要求。由於在拷貝和賦值動做以後,本來的auto_ptr和新產生的auto_ptr並不相等。本來的auto_ptr會交出擁有權,而不是拷貝給新的auto_ptr。
六、auto_ptr不是引用計數型的指針——這種指針保證,若是有一組智能型指針指向同一個對象,那麼當且僅當最後一個智能型指針被註銷時,該對象纔會被摧毀。對象

運用實例:內存

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

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

    return strm;
}

int main()
{
    auto_ptr<int> p(new int(42));
    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 += 13;
    p = q;
    cout << "after change and reassignment:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;

    return 0;
}

注意:output操做符的第二個參數是一個const refernce,因此並無發生擁有權的轉移。
七、不能以通常指針的賦值手法來初始化一個auto_ptr:資源

std::auto_ptr<int> p(new int(42));     //OK
std::auto_ptr<int> p = new int(24);    //ERROR

p = std::auto_ptr<int>(new int(24));   //OK
p = new int(24);                       // ERROR

下面一個例子展現const auto_ptr的特性:

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

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

    return strm;
}

int main()
{
    const auto_ptr<int> p(new int(42));
    const auto_ptr<int> q(new int(0));
    const auto_ptr<int> r;

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

    *q = *p;
    //*r = *p;    //ERROR:undefine behavior
    *p = -77;
    cout << "after assigning auto pointers:" << endl;
    cout << "p: " << p << endl;
    cout << "q: " << q << endl;
    cout << "r: " << r << endl;

    //q = p;    //ERROR at compile time
    //r = p;    //ERROR at compile time

    return 0;
}

注意下列賦值操做是錯誤的:     *r = *p; 這個句子對於一個「未指向任何對象」的auto_ptr進行提領操做。C++標準規定,這會致使未定義行爲,好比說致使程序的崩潰。

相關文章
相關標籤/搜索