我有C ++类如下
class anotherClass;
class myClass {
private:
myClass() {}
~myClass() {}
typedef std::map<string, anotherClass* > stringToClass;
static stringToClass s_stringToClass;
public:
static anotherClass* getStringToclass(string name);
};
上面的getStringToClass定义中的如下
anotherClass* myClass::getStringToClass(string name) {
stringToClass::iterator iter;
iter = s_stringToClass.find(name);
if(iter == s_stringToClass.end()) {
typedef stringToClass::value_type stringToClassPair;
anotherClass* pothClass = new anotherClass();
s_stringToClass.insert(stringToClassPair(name, pothClass));
return pothClass;
}
else {
return iter->second;
}
}
现在我的问题是我们正在如上定义的静态函数中分配内存。我们怎样才能删除内存?我们可以在析构函数中删除内存,因为析构函数不是静态的吗?
感谢您的帮助。
答案 0 :(得分:2)
该集合将自动清理,但其中的指针不会,所以你真的有两个选择:
后一种类型的类有提升但不确定它们有一个用于地图,我会选择前者。
我也会修改结构,以便不使用静态函数和静态映射,而是使用带有函数和映射的类,并且具有该类的静态(单例)实例。
您的函数也可能被修改为返回一个shared_ptr,但它仍然可以返回一个常规指针,因为该项目将永久保留在地图中,因此您无需担心它会失效。
因为它永远不会是NULL,你甚至可以返回一个引用。
typedef std::map<string, boost::shared_ptr<anotherClass> > stringToClass;
anotherClass& myClass::getStringToClass(string const& name)
{
boost::shared_ptr<anotherClass> & value = s_stringToClass[name];
if( !value )
{
value.reset( new anotherClass );
}
return *value;
}
您也可以考虑将其设置为线程安全。
答案 1 :(得分:0)
我会使用某种智能指针,例如Boost提供的指针,而不是原始指针。
答案 2 :(得分:0)
是的,您可以在析构函数中删除静态变量。
话虽如此,这不是一个好主意。如果您有两个类的实例,使用静态变量,一个被销毁,该怎么办?它的析构函数会删除内存,导致类的剩余实例出现问题。
除了你对静态成员的奇怪使用外,使用智能指针会更明智。
答案 3 :(得分:0)
如果将它存储在一个静态变量中,我猜你需要它们直到你的进程执行结束......如果没有,那么你需要添加一个方法来清除这个静态变量,删除每个元素并调用当你不再需要它时。
您不应该在析构函数中执行此操作,因为静态变量未链接到您的类实例。
答案 4 :(得分:0)
问题一:
函数永远不会返回指针(除非你真的真的有) 在这种情况下,你没有。
返回的指针没有所有权语义,因此不清楚指针的所有者是谁(如果你不知道谁拥有指针那么你就不知道谁可以删除它了。)
因此要么返回引用,要么返回智能指针 在这种情况下参考。因为所有动态创建的对象都在本地维护。
因为你显然是新手。使用boost :: shared_pointer。从技术上讲,这可能不是这种情况下最好的一种,但它是学习时最容易使用的。我会看看其他可用的智能指针,并了解何时适合使用每一个。
class anotherClass;
class myClass
{
private:
myClass() {}
~myClass() {}
typedef boost::ptr_map<string, anotherClass > stringToClass;
// ^^^ Note: Not std:: you are not allowed to add class to std::
static stringToClass s_stringToClass;
// Ownership now maintained by the map automatically.
public:
// Return a reference.
// We retain ownership inside this class
static anotherClass& getStringToclass(string name);
};
代码:
anotherClass& myClass::getStringToClass(string name)
{
stringToClass::iterator iter;
iter = s_stringToClass.find(name);
if(iter == s_stringToClass.end())
{
s_stringToClass[name] = new anotherClass();
return s_stringToClass[name];
}
else
{
return iter->second;
}
}
答案 5 :(得分:0)
我认为在你的情况下,析构函数不会有帮助,因为没有MyClass的任何对象。
我提出三种方法
1.不存储指针,存储对象本身。
2.将删除功能放入atexit;在你的情况下
class MyClass
{
.....//Your already existing code
static void Destroy()
{
//iterate s_StringToClass and delete them
}
static void getStringToClass( string name )
{
struct DestroySetter
{
DestroySetter()
{
atexit( MyClass::Destroy );
}
};
static DestroySetter setter; //Setup the destoyer
//Your existing code here
}
3.使用智能指针管理资源,建议使用shared_ptr。
虽然我采取了第二种方式,但我建议采用第三种方式。