返回一个指向函数静态数据的指针合适吗
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
作为一项可变任务,对性能来说毫无意义。
返回指针本身不是问题,但您必须定义一个关于谁创建谁销毁的干净"策略"。
在代码中,您定义了一个静态指针,该指针在第一次遇到其(指针)定义时就用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
中的代码是线程安全的,或者您的代码是单线程的,那么就没有问题。
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 静态数据成员模板专用化的实例化点在哪里
- 内联静态数据的初始化
- 调用在 HXX 文件中声明的静态数据成员
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- 静态数据成员:它"const declaration / constexpr definition"起作用?
- 关于静态常量数据模因的声明和定义的混淆
- 何时需要定义类的静态数据成员 (un/-)
- 为什么类成员数据必须是静态的才能被模板化类的模板化结构成员访问
- 为什么静态数据成员不能在c++11中的类中初始化
- 访问模板化类的非模板基的静态数据
- 静态数据成员的模板专用化
- 拒绝包含某些公共静态数据成员的类型
- GCC:在调试构建中优化的静态数据成员
- 类模板静态数据成员定义/声明/初始化
- 是否允许在作为静态数据结构成员的lambda函数中捕获变量
- C++ 中的静态数据成员
- 如果类在 C++ 中具有常量或引用类型的非静态数据成员,为什么编译器不提供默认赋值运算符?
- 使用 lambda 函数初始化静态数据成员