Boost學習筆記 -- memory management

RAII機制

爲了管理內存等資源,C++程序員通常採用RAII機制(資源獲取即初始化,Resource Acquisition Is Initialization ),在使用資源的類的構造函數中申請資源,然後使用,最後在析構函數中釋放資源。
如果對象是在棧上創建的,RAII機制可以正常工作;但如果對象是使用new在堆上創建的,那麼析構函數不會自動調用,程序員必須明確使用delete來釋放資源。

智能指針

boost.smart_ptr庫提供了6種智能指針:

  • scoped_ptr
  • shared_ptr
  • intrusive_ptr
  • weak_ptr
  • scoped_array
  • shared_array

使用方法

#include <boost/smart_ptr.hpp>
using namespace boost;

scoped_ptr

scoped_ptr的所有權很嚴格,不能轉讓,一旦scoped_ptr獲取了對象的管理權,你就無法再從它那裏取回來。

scoped_ptr<string> sp( new string( "text" ) );
cout << *sp << endl;
cout << sp->size() << endl;
sp++;   // wrong, scoped_ptr未定義遞增操作符
scoped_ptr<string> sp2 = sp;    //wrong, scoped_ptr不能拷貝構造
struct poxist_file {
    posix_file( const char* file_name ) {
        cout << "open file: " << file_name << endl;
    }
    ~posix_file() {
        cout << "close file" << endl;
    }
}

int main() {
    scoped_ptr<int> p( new int );
    if( p ) {
        *p = 100;
        cout << *p << endl;
    }

    p.reset();
    assert( p == 0 );
    if( !p ) {
        cout << "scoped_ptr == null" << endl;
    }

    // 將在離開作用域時自動析構,從而關閉文件釋放資源
    scoped_ptr<posix_file> fp( new posix_file( "/tmp/a.txt" ) );
}   // p和fp的指針自動被刪除

result:
100
scoped_ptr == null
open file: /tmp/a.txt
close file

scoped_array

scoped_array很像scoped_ptr,包裝了new[]操作符,它爲動態數組提供了一個代理,保證內存正確釋放。

int main() {
    int* arr = new int[ 100 ];
    scoped_array<int> sa( arr );

    fill_n( &sa[ 0 ], 100, 5 );
    sa[ 10 ] = sa[ 20 ] + sa[ 30 ];
}

如果可以使用STL的話,在需要動態數組的情況下我們使用std::vector,它比scoped_array提供了更多的靈活性,而只付出了很小的代價。

shared_ptr

shared_ptr是實現了引用計數的智能指針,可以被自由地拷貝和賦值,在任意的地方共享他,當沒有代碼使用(引用計數爲0)時才刪除被包裝的動態內存。

shared_ptr<int> sp( new int( 10 ) );
assert( sp.unique() );

shared_ptr<int> sp2 = sp;

assert( sp == sp2 && sp.use_count() == 2 );
*sp2 = 100;
assert( *sp == 100 );

sp.reset();
assert( !sp );
class shared {
private:
    shared_ptr<int> p;
public:
    shared( shared_ptr<int> p_):p( p_ ) {}
    void print() {
        cout << "count:" << p.use_count() << "v = " << *p << endl;
    }
};

void print_func( shared_ptr<int> p ) {
    cout << "count:" << p.use_count() << " v =" << *p << endl;
}

int main() {
    shared_ptr<int> p( new int( 100 ) );
    shared s1( p ), s2( p );

    s1.print();
    s2.print();

    *p = 20;
    print_func( p );

    s1.print();
}

注意,print_func()的參數是值傳遞,沒有使用引用,所以最後輸出如下:
count: 3 v = 100
count: 3 v= 100
count: 4 v= 20
count: 3 v = 20

工廠函數

shared_ptr的構造需要使用new,這導致了代碼的不對稱性(不需要使用delete),shared_ptr提供了一個工廠函數make_shared()來消除顯式的new調用。

#include <boost/make_shared.hpp>

int main() {
    typedef vector< shared_ptr< int > > vs;
    vs v( 10 );

    int i = 0;
    for( vs::iterator pos = v.begin(); pos != v.end(); ++pos ) {
        ( *pos ) = make_shared< int >( ++i );
        cout << *( *pos ) << ", ";
    }
    cout << endl;

    shared_ptr< int > p = v[ 9 ];
    *p = 100;
    cout << v[ 9 ] << endl;

    // using boost.foreach
    for( auto& ptr : v ) {
        ptr = make_shared< int >( ++i );
        cout << *ptr << ", ";
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章