gpt4 book ai didi

c++ - 在非模板化类析构函数中删除模板化类指针?

转载 作者:行者123 更新时间:2023-11-28 01:42:09 25 4
gpt4 key购买 nike

下面的代码test-templated-destructor.cpp复制我正在使用的图书馆的组织。我正在使用:

$ cat /etc/issue
Ubuntu 14.04.5 LTS \n \l
$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
$ g++ -std=c++14
g++: error: unrecognized command line option ‘-std=c++14’
g++: fatal error: no input files
compilation terminated.
$ g++ -std=c++11
g++: fatal error: no input files
compilation terminated.

有:

  • 基类 AA ,以及从中派生的类 BBCC ;
  • 抽象类 AAInstancer ,以及派生自它的类 AAInstancerTemplated这是模板化的
  • AAHandler ,它有一个模板函数 addTemplatedObject , 它存储 AAInstancer*指向 new AAInstancerTemplated<T>() 的指针对象,在 map类的属性
  • main() , 一个 AAHandler对象被实例化,.addTemplatedObject<BB>("BB");呼吁它

如果我运行 valgrind对此,它报告:

==21000== 43 (16 direct, 27 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==21000== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21000== by 0x40141B: void AAHandler::addTemplatedObject<BB>(std::string) (test-templated-destructor.cpp:64)
==21000== by 0x40113E: main (test-templated-destructor.cpp:82)

我认为问题在于我们使用了 newaddTemplatedObject() ,因此我们最晚应该在程序退出时相应地删除它——但没有这样做,这也是泄漏的原因。

所以我想,写一个遍历 instancers 的迭代器 map ,和 delete这些指针在 AAHandler 的析构函数中,但我不能:

  • 如果我写:
  ~AAHandler() {
cout << " (running AAHandler destructor)" << endl;
map<string, AAInstancer*>::iterator it;
for ( it = instancers.begin(); it != instancers.end(); it++ ) {
delete it->second;
}
}

...然后我开始编译:

$ g++ -g -Wall test-templated-destructor.cpp -o test-templated-destructor.exe
test-templated-destructor.cpp: In destructor ‘AAHandler::~AAHandler()’:
test-templated-destructor.cpp:60:18: warning: deleting object of abstract class type ‘AAInstancer’ which has non-virtual destructor will cause undefined behaviour [-Wdelete-non-virtual-dtor]
delete it->second;
^

... 听起来不错 - AAInstancer没有定义析构函数,因此编译器可能自动添加为非虚拟的,导致此警告(尽管通过 valgrind 运行它会显示不再检测到泄漏)。

  • 如果我写:
  template <class T>
~AAHandler() {
cout << " (running AAHandler destructor)" << endl;
map<string, AAInstancer*>::iterator it;
for ( it = instancers.begin(); it != instancers.end(); it++ ) {
delete (AAInstancerTemplated<T>*)it->second;
}
}

...希望如果我们调用addTemplatedObject,这个析构函数会被调用使用某些模板(无论如何都不会),编译失败:

$ g++ -g -Wall test-templated-destructor.cpp -o test-templated-destructor.exe && ./test-templated-destructor.exe
test-templated-destructor.cpp:57:14: error: destructor ‘AAHandler::~AAHandler()’ declared as member template
~AAHandler() {
^

... 这也是有道理的:AAHandler是一个非模板类,所以它的析构函数也不应该被模板化。

那么,有没有可能为AAHandler写一个析构函数呢? ,这将 delete所有new instancers 中的指针,无论它们是用哪个模板实例化的 - 对现有代码的更改最少(或最好,没有)?

test-templated-destructor.cpp

// g++ -g -Wall test-templated-destructor.cpp -o test-templated-destructor.exe && ./test-templated-destructor.exe
// valgrind --leak-check=yes ./test-templated-destructor.exe

#include <iostream>
#include <map>
using namespace std;

class AA {
public:
string myname;
AA() {
myname = "";
cout << " AA instantiated\n";
}
};


class BB : public AA {
public:
string mystuff;
BB() {
mystuff = "";
cout << " BB instantiated\n";
}
};

class CC : public AA {
public:
string mythings;
CC() {
mythings = "";
cout << " CC instantiated\n";
}
};

class AAInstancer
{
public:
virtual AA* createInstance() = 0;
string tagName;
};

template <class T>
class AAInstancerTemplated: public AAInstancer
{
public:
AA* createInstance() {
return new T();
}
};


class AAHandler
{
public:
~AAHandler() { }
AAHandler() { }
static map<string, AAInstancer*> instancers;

template <class T>
static void addTemplatedObject(string tagName) {
AAInstancer* instancer = new AAInstancerTemplated<T>();
instancer->tagName = tagName;
instancers[tagName] = instancer;
}

AAHandler* get() {
if(singleton == NULL)
singleton = new AAHandler();
return singleton;
}
private:
static AAHandler* singleton;
};
map<string, AAInstancer*> AAHandler::instancers;



int main()
{
AAHandler aah;
aah.addTemplatedObject<BB>("BB");

cout << "Address of aah: " << static_cast<void*>(&aah) << endl;
return 0;
}

最佳答案

AAInstancer 需要一个虚拟析构函数。如果它不需要正文,您可以默认它。

virtual ~AAInstancer() = default;

关于c++ - 在非模板化类析构函数中删除模板化类指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46714509/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com