--/--/--

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2009/05/21

std::vector にポインタを突っ込む

最近の仕事はもっぱら不慣れな C++ を使っていて、ようやくコツを掴みはじめた感じ。値とポインタだけの C ならまだ分かりやすかったのだけど、これに参照が混ざった途端にやたらと混乱した。

値として受け渡しのできないクラスのインスタンスを STLコンテナに突っ込みたいときには boost の shared_ptr みたいなスマートポインタでラップするのが安全でいいよって話はよく見かける。じゃあ生のポインタを突っ込んだらどうなるのというお話。結果は予想通りだったのだけど、まぁやってみたという記録だけ。

ちなみにその予想とは、コンテナを値で受け渡しても、それに内包されているポインタたちは値コピーされるだけ。ポインタが指してるオブジェクトの実体は、何も変わらない。shared_ptr ならコンテナが値渡しされるタイミングで、自身もコピーコンストラクタに渡される。この時(参照カウント方式で shared_ptr が実装されていれば)参照カウントが +1 され、渡した先のブロックが終了したタイミングで参照カウントが元に戻る。で、自分のブロックが終わったタイミングでカウントが 0 になり、オブジェクトの実体も破棄される(という仕組みだと思ってる)。

以下実験のコード。

#include <vector>
#include <iostream>

using std::vector;
using std::cout;
using std::endl;

class X {
public:
    X() { cout << "Default Constructor" << endl; }
    X(const X& x) { cout << "Copy Constructor" << endl; }
    X& operator=(const X& x) { cout << "op=" << endl; return *this; }
    ~X() { cout << "Destructor" << endl; }
};

void withValue(vector<X*> x) { cout << "withValue" << endl; }
void withRef(vector<X*>& x) { cout << "withRef" << endl; }
void withPtr(vector<X*>* x) { cout << "withPtr" << endl; }

void withValue(vector<X> x) { cout << "withValue" << endl; }
void withRef(vector<X>& x) { cout << "withRef" << endl; }
void withPtr(vector<X>* x) { cout << "withPtr" << endl; }

int main() {
    cout << "vecotr<X*>" << endl;
    vector<X*> xps;
    xps.push_back(new X());

    withValue(xps);
    withRef(xps);
    withPtr(&xps);

    vector<X*>::iterator i;
    for (i = xps.begin(); i != xps.end(); ++i) {
        delete *i;
    }

    cout << endl << endl;

    cout << "vecotr<X>" << endl;
    vector<X> xs;
    xs.push_back(X());

    withValue(xs);
    withRef(xs);
    withPtr(&xs);

    return 0;
}

結果。

$ ./a.out
vector<X*>
Default Constructor
withValue
withRef
withPtr
Destructor


vector<X>
Default Constructor
Copy Constructor
Destructor
Copy Constructor
withValue
Destructor
withRef
withPtr
Destructor

原則、生のポインタを STL コンテナに突っ込むようなことはしないほうがいいのだろうけど。shared_ptr が使えないとか、shared_ptr を自前で実装するのが面倒なときなんかは気をつけて使ったりするといいんじゃなかろーか。いやよくはないか。

スポンサーサイト

comment

post




上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。