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>. 会有各种各样的模板类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);

我不想使用移动语义等 C++11 特性的原因,或者std::shared_ptr我不想强迫我的队友在他们的计算机上安装更新版本的 g++。我不能给他们库的编译版本,因为它是大量模板化的。

编辑 该库将被线程化。特别是,TriangularMF<T>::minImplicate它将同时在多个线程中运行。所以,做minImplicate一个相互的任务,对性能没有意义。

4

3 回答 3

3

这是单身人士常用的成语:

class CMyClass {};

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

CMyClass 将在第一次 MyClass() 函数调用时构建。

它看起来很像您的代码,除了指针异常,它会导致销毁此类 crated 实例时出现问题。如果你不想在这里使用 shared_ptr,那么考虑编写你自己的 shared_ptr 样模板,那么它应该可以正常工作。

[编辑] 如果这段代码要在多线程环境中使用,那么在这里使用智能指针会很棘手

于 2012-07-14T19:40:11.103 回答
3

返回指针本身并不是问题,但您必须定义关于 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)在返回时解锁。

于 2012-07-14T19:46:22.283 回答
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 回答