簡體   English   中英

返回指向函數靜態數據的指針是否合適?

[英]Is it appropriate to return a pointer to static data of a function?

好吧,我需要返回一個指向將在函數內創建的類實例的指針。 這個合適嗎?

這是示例代碼:

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>派生。 會有各種模板類,比如TriangularMF ,它們有一個從ImplicatedMembershipFunction<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);

我不想使用移動語義或std::shared_ptr等C ++ 11功能的原因是我不想強迫我的隊友在他們的計算機上安裝更新版本的g ++。 我不能給他們一個庫的編譯版本,因為它是模仿的。

編輯該庫將是線程化的。 特別是, TriangularMF<T>::minImplicate將同時在多個線程中運行。 因此,使minImplicate成為一個mutal任務,對性能毫無意義。

這是單身人士常用的習語:

class CMyClass {};

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

CMyClass將在第一個MyClass()函數調用上構建。

它看起來很像你的代碼,指針除外,它會導致破壞這種crated實例的問題。 如果您不想在這里使用shared_ptr,那么考慮編寫自己的shared_ptr之類的模板,那么它應該可以正常工作。

[編輯]如果這個代碼將在多線程環境中使用,那么在這里使用智能指針將是棘手的

返回指針本身不是問題,但你必須定義一個關於whoi創建和銷毀誰的干凈“策略”。

在您的代碼中,您定義了一個靜態指針,該指針在第一次遇到其(指針)定義時使用new對象進行初始化。

指針本身將在main()返回后被銷毀,但它指向的對象呢? 如果你讓別的東西來處理刪除,你的函數將繼續返回指針,即使對象不再存在。 如果你把它放在那里,它將在程序結束時被殺掉(不是“危險的”泄漏,因為它只是一個對象,但如果它的析構函數必須采取一些合理的行動呢?)

您最有可能聲明,而不是靜態指針,而是靜態OBJECT,並返回...其地址或其引用。

以這種方式,對象被授予存在直到程序終止並在main()返回后被正確銷毀。

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

請注意,我刪除了“對...做某事”,因為它將每次執行(而不僅僅是第一次)。要初始化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)它之前鎖定它if(init) ,在返回時解鎖。

您可以使用此技術,但返回引用。 如果調用者需要指向存儲的指針,則可以獲取結果的地址。

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的代碼是線程安全的,或者您的代碼是單線程的,那么就沒有問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM