3

さて、関数内で作成されるクラスのインスタンスへのポインターを返す必要があります。これは適切ですか?

これはサンプルコードです:

template <typename T>
ImplicatedMembershipFunction<T>* 
TriangularMF<T>::minImplicate(const T &constantSet) const
{
    static ImplicatedType* resultingSet = new ImplicatedType();
    // do something to generate resultingSet...
    return resultingSet;
}

コンテナーに基本クラスのサブクラスが必要なため、ポインターを返したい。上記のコードでは、 で定義され、 から派生しImplicatedTypeたクラスです。から派生したネストされたクラスを持つようなさまざまなテンプレート クラスがあり、それらを同じように扱う必要があります。たとえば、図書館の外では、次のようなことをしたいかもしれません:TriangularMF<T>ImplicatedMembershipFunction<T>TriangularMFImplicatedMembershipFunction<T>

TriangularMF<double> trmf(0,1,2);
TrapesoidalMF<double> trpmf(0,1,3,2); // a class like TriangularMF but
                                      // ImplicatedType is different 
ImplicatedMembershipFunction<double>* itrmf = trmf.implicate(0.6);
ImplicatedMembershipFunction<double>* itrpmf = trpmf.implicate(0.6); // same as above.

// use them in the same way:
vector<ImplicatedMembershipFunction<double>*> vec;
vec.push_back(itrmf); 
vec.push_back(itrpmf);

移動セマンティクスのような C++11 機能を使用したくない理由、またはstd::shared_ptrチームメイトに g++ の新しいバージョンをコンピューターに強制的にインストールさせたくないという理由があります。ライブラリのコンパイル済みバージョンを提供することはできません。

編集 ライブラリはスレッド化されます。特に、 はTriangularMF<T>::minImplicate同時に複数のスレッドで実行されます。したがって、minImplicate相互タスクを作成しても、パフォーマンスには意味がありません。

4

3 に答える 3

3

ポインターを返すこと自体は問題ではありませんが、whoi の作成と破棄に関する明確な「ポリシー」を定義する必要があります。

コードではnew、(ポインター) 定義が最初に検出されたときにオブジェクトで初期化される静的ポインターを定義します。

ポインター自体は、が戻った直後に破棄されますがmain()、それが指しているオブジェクトはどうなるでしょうか。他の何かに削除を処理させると、オブジェクトが存在しなくなっても、関数は引き続きそのポインターを返します。そこに置くと、プログラムの最後で削除されます (「危険な」リークではありません。これは 1 つのオブジェクトにすぎませんが、そのデストラクタが適切なアクションを実行する必要がある場合はどうでしょうか?)

静的ポインターではなく静的 OBJECT を宣言し、そのアドレスまたはその参照を返す可能性が最も高くなります。

このようにして、オブジェクトはプログラムの終了まで存在し、返された後に適切に破棄されることが許可されmain()ます。

template <typename T>
ImplicatedMembershipFunction<T>* 
TriangularMF<T>::minImplicate(const T &constantSet) const
{
    static ImplicatedType resultingSet(....);
    return &resultingSet;
} 

「do something to ...」は(最初だけでなく)毎回実行されるため、削除したことに注意してください。初期化ImplicatedTypeするには、コンストラクターに依存することをお勧めします。または、一発で構築できない場合は、次のようにします

template <typename T>
ImplicatedMembershipFunction<T>* 
TriangularMF<T>::minImplicate(const T &constantSet) const
{
    static ImplicatedType* resultingSet=0;
    static bool init=true;
    if(init)
    {
        init=false; 
        static ImplicatedType result;
        resultingSet=&result;
        // do something to generate resultingSet...
    }
    return resultingSet;
}

マルチスレッドの状況にある場合は、静的ミューテックスも必要であり、前if(init)にロックし、戻り時にロックを解除します。

于 2012-07-14T19:46:22.283 に答える
3

これは、シングルトンで一般的に使用されるイディオムです。

class CMyClass {};

CMyClass& MyClass() {
  static CMyClass mclass;
  return mclass;
}

CMyClass は、最初の MyClass() 関数呼び出しで構築されます。

そのようなクレートされたインスタンスを破壊する際に問題を引き起こすポインタを除いて、それはあなたのコードのように見えます。ここで shared_ptr を使用したくない場合は、独自の shared_ptr のようなテンプレートを作成することを検討してください。

[編集] このコードがマルチスレッド環境で使用される場合、ここでスマート ポインターを使用するのは難しいでしょう。

于 2012-07-14T19:40:11.103 に答える
1

この手法を使用できますが、参照を返します。格納するポインターが必要な場合、呼び出し元は結果のアドレスを取得できます。

template <typename T>
ImplicatedMembershipFunction<T> &
TriangularMF<T>::minImplicate(const T &constantSet) const
{
    static ImplicatedType* resultingSet = new ImplicatedType();
    // do something to generate resultingSet...
    return *resultingSet;
}

ただし、コードの危険性は、本質的に MT セーフではないことです。ただし、内部のコードminImplicateがスレッド セーフであることがわかっている場合、またはコードがシングル スレッドであることがわかっている場合は、問題はありません。

于 2012-07-14T19:25:03.267 に答える