两步物体破坏背后的原因是什么? [英] What is the reasoning behind two-step object destruction?

查看:169
本文介绍了两步物体破坏背后的原因是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在游戏开发世界中,我经常看到使用单独的 initialize() uninitialize() shutdown()方法。这不仅包括多个教程,还包括长期建立和大型现实世界项目,如一些现代游戏引擎。我最近在Cry Engine 3中看到过一个类,它不仅使用了一个 shutdown()方法,而且直到调用这个。〜Foo (),它基于我对C ++知道的一切,不能真的被认为是一个很好的设计。

In the games development world I often see classes using separate initialize() and uninitialize() or shutdown() methods. This includes not only multiple tutorials, but also long-established and large real-world projects, like some modern game engines. I've recently seen a class in Cry Engine 3 which not only uses a shutdown() method, but goes as far as calling this.~Foo() from it, which based on everything I know about C++, can't really be considered a good design.

虽然我可以看到来自两步初始化的一些好处,并且有很多讨论,我不明白两步破坏背后的原因。为什么不以析构函数的形式使用C ++语言提供的默认设置,但是有一个单独的 shutdown()方法,析构函数留空?为什么不走得更远,使用现代C ++将一个对象持有的所有资源放入智能指针中,所以我们不必担心手动释放它们。

While I can see some of the benefits that come from two-step initialization, and there are many discussions about it, I can't understand the reasoning behind the two-step destruction. Why not use the default facilities provided by C++ language in form of the destructor, but have a separate shutdown() method and the destructor left empty? Why not go even further and, using modern C++, put all the resources held by an object into smart pointers so we don't have to worry about releasing them manually.

基于不再适用的原则的两步破坏,一些过时的设计,还是有一些有效的理由来使用它来控制对象生命周期的标准方法?

Is two-step destruction some outdated design based on principles that no longer apply or are there some valid reasons to use it over standard ways of controlling objects' lifetime?

推荐答案

如果您不想阅读,则要点是您需要异常来从ctors和异常返回错误。

If you don't want to read, the gist is that you need exceptions to return errors from ctors and exceptions are bad.

正如Trevor和其他人所暗示的,这种做法有很多原因。您已经提出了这里的具体示例,所以让我们来谈谈。

As Trevor and others have hinted at, there are a number of reasons for this practice. You've brought up a specific example here though, so let's address that.

本教程涉及包含以下定义的类 GraphicsClass (该名称确实不激发信心):

The tutorial deals with a class GraphicsClass (the name sure doesn't inspire confidence) which contains these definitions:

class GraphicsClass
{
public:
    GraphicsClass();
    ~GraphicsClass();
    bool Initialize(int, int, HWND);
    void Shutdown();
};

所以它有ctor,dtor和初始化/关闭。为什么不把后者压缩成前者?实现给出了一些线索:

So it has ctor, dtor, and Initialize/Shutdown. Why not condense the latter into the former? The implementation gives a few clues:

bool GraphicsClass::Initialize(int screenWidth, int screenHeight, HWND hwnd)
{
    bool result;

    // Create the Direct3D object.
    m_D3D = new D3DClass;
    if(!m_D3D)
    {
        return false;
    }

    // Initialize the Direct3D object.
    result = m_D3D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK);
        return false;
    }

    return true;
}

确定,检查新D3DClass failed is pointless(只有当我们用完了内存 我们已经覆盖了新的不抛出 bad_alloc的 )*。检查看到 D3DClass :: Initialize()失败可能不是。正如其签名提示,它试图初始化与图形硬件相关的一些资源,有时可能在正常情况下会失败 - 也许所请求的解决方案太高或资源正在使用中。我们想要优雅地处理,我们不能在ctor中返回错误,我们只能抛出异常。

Ok sure, checking to see if new D3DClass fails is pointless (it only happens if we run out of memory and we've overridden new to not throw bad_alloc)*. Checking to see D3DClass::Initialize() fails may not be though. As its signature hints at, it's trying to initialise some resources related to graphics hardware, which can sometimes fail in normal circumstances - maybe the resolution requested is too high, or the resource is in use. We'd want to handle that gracefully, and we can't return errors in the ctor, we can only throw exceptions.

这当然引起了一个问题:为什么我们抛出异常? C ++异常非常慢。如此缓慢的意见非常强大特别是在游戏开发中。另外你不能扔在dtor ,所以有乐趣试图说,把网络资源终止在那里。大多数,如果不是全部,C ++游戏已经被关闭了例外。

Which of course raises the question: why don't we throw exceptions? C++ exceptions are very slow. So slow that opinions of it are very strong, especially in game development. Plus you can't throw in the dtor, so have fun trying to say, put network resource termination there. Most, if not all, C++ games have been made with exceptions turned off.

这是主要原因;我不能折扣其他的,有时甚至更糟糕的原因,例如有一个C遗产(没有ctors / dtors),或者一对有模块A和B的模块相互引用的架构。当然还记得游戏开发的#1的优先事项是船只游戏,不会创建完美的和可维护的架构,所以你有时会看到这样的愚蠢的做法。

That's the main reason anyway; I can't discount other, sometimes sillier, reasons though, such as having a C legacy (where there are no ctors/dtors), or an architecture that has pairs of modules A and B hold references to each other. Of course remember games development's #1 priority is to ship games, not create perfectly robust and maintainable architectures, so you sometimes see silly practices like this.

我听说C ++委员会深深地意识到问题的例外有,但iirc最新的是,它被放在太难的桶,所以你会看到更多的游戏在未来许多年。

I hear that the C++ committee is deeply aware of the problems that exceptions have, but iirc the latest is that it's been put in the "too hard" bucket, so you'll see more of this in games for many years to come.

* - 阿哈!所以检查看看,如果新的D3DClass 不是没有意义,因为我们可能禁用了异常,所以这是检查失败的内存的唯一方法分配等等。

*- Aha! So checking to see if new D3DClass wasn't pointless, as we've probably disabled exceptions so this is the only way to check for failed memory alloc, among other things.

这篇关于两步物体破坏背后的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆