返回一个指向函数静态数据的指针合适吗

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

本文关键字:数据 静态 指针 函数 一个 返回      更新时间:2023-10-16

好吧,我需要返回一个指针,指向将在函数内创建的类的实例。这合适吗?

这是示例代码:

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作为一项可变任务,对性能来说毫无意义。

返回指针本身不是问题,但您必须定义一个关于谁创建谁销毁的干净"策略"。

在代码中,您定义了一个静态指针,该指针在第一次遇到其(指针)定义时就用new对象初始化。

指针本身将在main()返回后被销毁,但它所指向的对象呢?如果让其他东西来处理删除,那么即使对象不在了,函数也会继续返回该指针。如果你让它在那里,它将在程序结束时被杀死(不是"危险的"泄漏,因为它只是一个对象,但如果它的析构函数必须采取一些合理的行动呢?)

您最可能声明的不是静态指针,而是静态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)之前将其锁定,并在返回时解锁。

这是单身汉常用的习语:

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

CMyClass将在第一个MyClass()函数调用中构造。

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

[edit]如果这段代码要在多线程环境中使用,那么在这里使用智能指针将是一件棘手的事情

您可以使用此技术,但返回一个引用。如果调用方需要存储指针,则可以获取结果的地址。

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中的代码是线程安全的,或者您的代码是单线程的,那么就没有问题。