0

私は長い間、この問題の答えを探していました。

共有データ (shared_ptr など) を、可能な場合と必要な場合に使用したいと考えています。しかし、仮想関数も使いたいです。以下に示すように、それらを一緒に使用することには矛盾があります。

この方法でクラスのデータを保護します。

class MyObject {
public:
    void method() {
        // no memory leak here, because this contains
        // count of references of Data inside shared_ptr
        OtherObject::otherMethod(this);
    }
private:
    class Data {};
    shared_ptr<Data> data;
};

クラス MyObject を単に shared_ptr 内にネストすると、何らかのメソッドで MyObject クラスの外部にある "this" 生ポインタを安全に渡すことができないためです。生ポインタは参照カウントで保護されていません。

例:

class MyObject {
public:
    void method() {
        // memory leak here, because this does not contain
        // count of references of Data or of self (MyObject) 
        OtherObject::otherMethod(this);
    }
private:
    class Data {};
    Data data;
};

...

shared_ptr<MyObject> crazyLeakingObject;

内部にすべてのデータとメソッドを含む MyObject があるため、crazyLeakingObject がリークしますが、参照の数に関する情報がない MyObject のみです。MyObject のメソッドには、そのような情報はありません。

仮想関数が必要ない場合に使用する最初のアプローチ。しかし、2 つ目は仮想機能用です。ご存知のように、既存のオブジェクトのポインター (生のポインター) を介してのみ vtable にアクセスできます。ただし、生のポインターと保護された共有ポインターは反対です。この 2 つのアプローチを一緒に使用すると、私のプロジェクトのアーキテクチャが乱雑になります。そして、2番目のアプローチには漏れがあります。

仮想関数と自動参照カウントを使用する方法はありますか? 例はどこにありますか? 問題に直面しましたか?

私は英語のネイティブ スピーカーではないので、説明を求めてもかまいません。

前もって感謝します。

4

2 に答える 2

1

次の仮想関数を使用できますshared_ptr

struct Base {
    virtual ~Base() {}
    void foo() { std::cout << "base\n"; }
};

struct Derived : Base {
    void foo() { std::cout << "derived\n"; }
};

int main() {
    shared_ptr<Base> ptr(new Derived());
    ptr->foo(); // prints "derived"
} // object is deleted at function return

OtherObject::otherMethod呼び出し元の参照よりも長く続く可能性があるように、引数をどこかに保存する場合、問題が発生する可能性があります。生のポインターの代わりに を渡し、Boost を使用shared_ptrして、 のコードがオブジェクト自体への共有ポインターを取得し、 に渡すことができます。しかし、関連するコードを見ないと、それが必要かどうか、または良いアイデアかどうかわかりません。otherMethodenable_shared_from_thismethodotherMethod

于 2012-06-27T16:33:36.713 に答える
1

std::enable_shared_from_this を使用して、共有オブジェクトの this ポインターを渡したい...

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this/enable_shared_from_this

于 2012-06-27T17:21:27.197 に答える