我有这个单例模式,运行正常。但是当我用valgrind执行我的程序来检查内存泄漏时,似乎实例永远不会被破坏。
我的错误在哪里?
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();
};
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;
}
这没关系,但在初始化时,我从文件中读取了一堆单词,然后将它们保存在地图实例中。
由于
答案 0 :(得分:15)
Stopwords::~Stopwords() {
delete instance;
}
这是类的实例的析构函数。您可能希望在程序结束时调用此函数,就好像它是一种“静态”析构函数,但这不是它。
因此,对于Stopwords实例的析构函数会启动对Stopwords实例的破坏;你在这里有一个无限循环,你永远不会进入。如果你进入这个循环,那么程序可能会崩溃。
有一种更简单的方法可以做单例:不要将实例保持为手动分配的静态类成员,而只需将其保存为静态函数变量。 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;
};
此外,您应该将不需要修改类的成员函数标记为const
:
std::map<std::string,short> getMap() const;
答案 1 :(得分:11)
问题是你永远不会手动调用析构函数或删除实例指针,即从类外部调用。因此析构函数中的删除将永远不会被执行,这意味着析构函数永远不会被执行,这意味着删除永远不会被执行,这意味着......你看到你在那里做了什么?你的析构函数间接地称自己为自己不顺利。而且你永远不会从外面打电话,所以它永远不会被召唤 - 幸运的是。
你应该改变你的单身实现,也许是Meyers单身(查找),甚至更好不要使用单身。在像这样的情况下,如果它们是数据源,那么处理模式的弱点就太多了。
答案 2 :(得分:1)
所以结论是你的实例永远不会被杀死。
通常,当你使用单身时,你不必在程序结束前杀死它。你为什么需要这个?
如果你不这样做,你最好使用static
关键字明确说明它在程序完成之前一直存在。
static Singleton& getInstance()
{
static Singleton s;
return s;
}
答案 3 :(得分:-1)
通过在实例getter中使实例成为函数静态std :: unique_ptr而不是类静态变量,可以在C ++中实现单例。这确保了在程序完成时调用析构函数,并允许您创建一个以多态方式访问的实例,例如:通过指向抽象基类的指针。
答案 4 :(得分:-6)
在您的析构函数中,您可以:
Stopwords::~Stopwords() {
delete instance;
}
我建议你补充一下:
Stopwords::~Stopwords() {
delete instance;
instance = 0;
}
此调用确保指针不仅从内存中删除,而且指向任何内容。删除指针时,您需要确保它不再指向任何内容,否则您可能会发生内存泄漏。