C++ 用Shutdown()方法而不是析构函数清除

C++ 用Shutdown()方法而不是析构函数清除,c++,directx,game-engine,class-design,C++,Directx,Game Engine,Class Design,在中,它们有空的构造函数和析构函数,而是使用initialize()和shutdown()函数来初始化和清理对象。使用此设计一段时间后,我多少能理解使用initialize()方法的好处,但我看不出使用shutdown()方法比将所有清理代码放入析构函数更好 它们提供的原因如下: 您还会注意到,我没有在类析构函数中清理任何对象。相反,我在Shutdown函数中清理了所有对象,您将在下面看到。原因是我不相信有人会叫它。某些windows函数,如ExitThread(),因未调用类析构函数而导致内存

在中,它们有空的构造函数和析构函数,而是使用
initialize()
shutdown()
函数来初始化和清理对象。使用此设计一段时间后,我多少能理解使用
initialize()
方法的好处,但我看不出使用
shutdown()
方法比将所有清理代码放入析构函数更好

它们提供的原因如下:

您还会注意到,我没有在类析构函数中清理任何对象。相反,我在Shutdown函数中清理了所有对象,您将在下面看到。原因是我不相信有人会叫它。某些windows函数,如ExitThread(),因未调用类析构函数而导致内存泄漏而闻名。当然,现在可以调用这些函数的更安全版本,但我只是在windows上编程时要小心

因此,一般使用模式如下所示:

class Renderer
{
public:
    Renderer() { }
    ~Renderer() { }

    bool initialize(...) { /* perform initialization */ }
    void shutdown() { /* clean-up */ }
}; 

Renderer* renderer = new Renderer;
renderer->initialize(...);

// use the renderer

renderer->shutdown();
delete renderer;
renderer = NULL;

<> P> >在查看ResteTK的代码时,我觉得它们来自C背景(在函数顶部初始化所有变量,只使用原始指针和原始数组等),所以我想知道这是否是现代C++中不必要的另一件事(因为它使使用智能指针变得更困难)。这种设计有什么真正的好处吗?

一般来说,建议不要在析构函数中进行清理

但是,如果clean操作可能失败,并且希望抛出异常,则可以这样做。然后您必须小心,因为另一个异常会调用abort()。对于这种特殊情况,在单独的函数中进行清理是有意义的

顺便说一下,这个代码示例看起来确实像来自c世界的人

原因是我不相信有人会叫它。某些windows函数,如ExitThread(),因未调用类析构函数而导致内存泄漏而闻名

这是正确的,但要尽量避免此类功能。也来自:

在C++11(我知道)中,没有一种可移植的方法可以不合作地杀死多线程程序中的单个线程(即不杀死所有线程)


因此,只要让线程顺利完成,就会调用析构函数。

这个参数根本不适用。如果调用了
ExitThread
(或
std::exit
,或任何其他退出的函数),则肯定不会调用
shutdown
。使用
new
创建对象的方式也完全没有必要。如果你对C++及其风格了解不多,我建议不要这样学习。如果你这样做了,就用你所知道的来代替它。@chris我认为论点是如果你在堆栈上的某个地方创建一个对象,比如说
main
,并希望调用析构函数,你可能会失望。除非您有一个
shutdown
函数,否则无法自己调用析构函数(在本例中)。当然,这不是一个很好的论点,而且只有当你销毁你的对象时它才起作用。@user3125280,当然有可能:
obj.~Class()。我并不是说这是一件特别好的事情,但是如果你打算在没有被调用的情况下退出,这是有可能的。如果你的
关闭
代码可能会抛出异常,那么你可能会想要分离代码,在这种情况下,析构函数的语义实际上是“放弃”而不是“清理”。即使如此,析构函数可以吞咽异常,而
关闭
不能吞咽异常。至少给出一种方法,尽可能地自动清理。没错。因为这个问题我没有得到任何答案,所以我在gamedev上问了一个类似的问题,引起了更多的关注,但后来又回到了原来的问题:我得到的答案与您所说的一致,加上这样的解决方案,在使用自定义内存分配时可能会很有用。