单例模式析构函数 C++
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20098254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Singleton pattern destructor C++
提问by user3013172
i have this singleton pattern and it runs ok. But when i execute my program with valgrind to check memory leaks, it seems that the instance is never destroyed.
我有这个单例模式,它运行正常。但是当我用 valgrind 执行我的程序来检查内存泄漏时,似乎该实例永远不会被破坏。
Where is my mistake?
我的错误在哪里?
Header
标题
class Stopwords {
private:
static Stopwords* instance;
std::map<std::string,short> diccionario;
private:
Stopwords();
public:
~Stopwords();
public:
static Stopwords* getInstance();
std::map<std::string,short> getMap();
};
.cpp
.cpp
Stopwords* Stopwords::instance = NULL;
Stopwords::Stopwords() {
diccionario = map<string,short>();
char nombre_archivo[] = "stopwords/stopwords.txt";
ifstream archivo;
archivo.open(nombre_archivo);
string stopword;
while(getline(archivo,stopword,',')) {
diccionario[stopword] = 1;
}
archivo.close();
}
Stopwords::~Stopwords() {
delete instance;
}
Stopwords* Stopwords::getInstance() {
if (instance == NULL) {
instance = new Stopwords ();
}
return instance;
}
map<string,short> Stopwords::getMap(){
return diccionario;
}
It's not relevant but in the initialization, i read a bunch of words from a file and i save them in a map instance.
它不相关,但在初始化时,我从文件中读取了一堆单词并将它们保存在地图实例中。
Thanks
谢谢
回答by bames53
Stopwords::~Stopwords() {
delete instance;
}
This is the destructor for instances of the class. You probably intended this function to be called when the program ends, as though it were a kind of 'static' destructor, but that's not what this is.
这是类实例的析构函数。您可能打算在程序结束时调用此函数,就好像它是一种“静态”析构函数,但事实并非如此。
So your destructor for instances of Stopwords initiates destruction of Stopwords instances; You've got an infinite loop here, which you never enter. If you do get into this loop then the program will probably just crash.
所以你的停用词实例的析构函数会启动停用词实例的销毁;你在这里有一个无限循环,你永远不会进入。如果你进入这个循环,那么程序可能会崩溃。
There's a simpler way to do singletons: Instead of keeping the instances as a static class member that you allocate manually, simply keep it as a static function variable. C++ will manage creating and destroying it for you.
有一种更简单的方法来做单例:不要将实例保留为手动分配的静态类成员,只需将其保留为静态函数变量即可。C++ 将为您管理创建和销毁它。
class Stopwords {
public:
static Stopwords &getInstance() {
static Stopwords instance;
return instance;
}
~Stopwords();
std::map<std::string,short> getMap();
private:
Stopwords();
std::map<std::string,short> diccionario;
};
Also, you should mark member functions that don't need to modify the class as const
:
此外,您应该将不需要修改类的成员函数标记为const
:
std::map<std::string,short> getMap() const;
回答by Arne Mertz
The problem is that you never call the destructor or delete on the instance pointer by hand, i.e. from outside the class. So the delete inside the destructor will never get executed, meaning the destructor will never get executed, meaning the delete will never get executed, meaning... You see what you did there? Your destructor is indirectly calling itself which will not go well. And you never call it from the outside, so it never gets called at all - luckily.
问题是您永远不会手动调用析构函数或删除实例指针,即从类外部调用。所以析构函数中的删除永远不会被执行,这意味着析构函数永远不会被执行,意味着删除永远不会被执行,意思是......你看到你在那里做了什么吗?您的析构函数间接调用自身,这不会顺利。你永远不会从外面调用它,所以它永远不会被调用 - 幸运的是。
You should change your singleton implementation, maybe a Meyers singleton (look it up), or even better not use a singleton at all. In cases like this one, where they are data sources, there are just too much weaknesses of the pattern to deal with.
您应该更改您的单例实现,也许是 Meyers 单例(查找一下),或者甚至最好根本不使用单例。在这种情况下,它们是数据源,模式的弱点太多了。
回答by klm123
- You allocate memory for instance with new. So the instance will be alive until delete is called.
- Destructor is called in the case an instance of a class going to be killed.
- Nothing kills (using delete) your instance, but destructor itself.
- 例如,您使用 new 分配内存。因此,该实例将一直存在,直到调用 delete 为止。
- 在类的实例将被杀死的情况下调用析构函数。
- 没有什么可以杀死(使用删除)您的实例,但析构函数本身。
So the conclusion is that your instance is never killed.
所以结论是你的实例永远不会被杀死。
Usually, when you use singleton you don't care to kill it before the program finishes. Why do you need this?
通常,当您使用单例时,您并不关心在程序完成之前杀死它。你为什么需要这个?
If you don't you better use static
keyword to make explicit the fact that it is alive until the program finishes.
如果你不这样做,你最好使用static
关键字来明确说明它在程序完成之前一直存在。
static Singleton& getInstance()
{
static Singleton s;
return s;
}
回答by user2282212
You can implement singleton in C++ by making the instance a function-static std::unique_ptr inside the instance getter, rather than a class-static variable. This ensures a call of destructor upon program's completion, and lets you create an instance that gets accessed polymorphically e.g. through a pointer to an abstract base class.
您可以在 C++ 中实现单例,方法是使实例成为实例 getter 中的函数静态 std::unique_ptr,而不是类静态变量。这确保在程序完成时调用析构函数,并允许您创建一个实例,该实例可以多态访问,例如通过指向抽象基类的指针。
回答by TurnsCoffeeIntoScripts
In your destructor you do:
在您的析构函数中,您执行以下操作:
Stopwords::~Stopwords() {
delete instance;
}
I would suggest you add:
我建议你添加:
Stopwords::~Stopwords() {
delete instance;
instance = 0;
}
This call makes sure that the pointer is not only removed from memory but points to nothing. When deleting a pointer you need to make sure it doesn't point to nothing anymore otherwise you may get memory leaks indeed.
此调用确保指针不仅从内存中删除,而且指向任何内容。删除指针时,您需要确保它不再指向任何内容,否则您确实可能会出现内存泄漏。