Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SDL中错误处理和清理资源的良好实践?_C++_Error Handling_Sdl_Code Cleanup - Fatal编程技术网

C++ SDL中错误处理和清理资源的良好实践?

C++ SDL中错误处理和清理资源的良好实践?,c++,error-handling,sdl,code-cleanup,C++,Error Handling,Sdl,Code Cleanup,在使用SDL时,我一直在处理错误(例如,在SDL初始化期间),每当函数中遇到错误时,我都返回false,否则返回true。然后通过调用main()函数末尾的close()函数执行清理,如下所示: int main(){ if(!init()){ // do some stuff } ... close(); return 0; } close()函数: void close(){ SDL_DestroyRenderer(g_R

在使用SDL时,我一直在处理错误(例如,在SDL初始化期间),每当函数中遇到错误时,我都返回
false
,否则返回
true
。然后通过调用
main()
函数末尾的
close()
函数执行清理,如下所示:

int main(){
    if(!init()){
        // do some stuff
    }

    ...

    close();
    return 0;
}
close()
函数:

void close(){
    SDL_DestroyRenderer(g_Renderer);
    SDL_DestroyWindow(g_Window); 

    IMG_Quit();
    SDL_Quit();
}
然而,我意识到这种清理方法意味着我不能真正抛出异常,因为不会调用
close()
函数。 在做了一点阅读之后,我决定,除非出于性能相关的原因(我听说这很重要,尤其是在游戏开发中),否则我将尽量不抛出异常

此外,这意味着随着程序的增长,我需要添加更多的函数来清理
close()
,这似乎不切实际,而且很容易忘记

因此,我的问题是:

  • 一般来说,在使用SDL时,我们应该在什么时候提出异常?除非需要,否则通常避免使用它们是否被视为良好做法
  • 为了允许使用异常,应该如何清理SDL资源?我已经研究了一些方法,但我不确定何时使用每种方法,或将每种方法结合使用:
      创建一个C++包装器类,以处理构造函数中的初始化和析构函数中的清理
    • 通过正常初始化SDL对象来使用
      unique_ptr
      (或其他智能指针),并提供一个用于清理的deleter类
    • 使用
      atexit()
      处理
      SDL\u Quit()
      IMG\u Quit()
  • 我曾考虑实现一个包装类,但后来意识到,如果在初始化过程中出现错误,我可能需要抛出一个异常,例如从
    SDL\u CreateWindow()
    ,我正试图避免这种情况。有什么帮助或建议吗

  • 使用
    atexit()
    处理
    SDL\u Quit()
    IMG\u Quit()

  • 我不会使用
    atexit
    。其他替代方案可以让您更好地控制何时进行清理

  • 通过正常初始化SDL对象来使用
    unique_ptr
    (或其他智能指针),并提供一个用于清理的deleter类

  • 这可能行得通,但我不喜欢这种方法。它可以用来清理指针,比如
    SDL\u Window*
    ,但是如果需要清理的不是指针怎么办?(例如,如果您想自动调用
    SDL\u Quit()

    使用
    unique\u ptr
    清理指针和其他清理其他东西的方法会毫无理由地在代码中引入不一致性,因此我会完全避免它(内存管理除外)

  • < P>创建C++包装器类,以处理构造函数中的初始化和析构函数

    中的清理
  • 这是个好主意

    如果你要做,别忘了跟着做。删除复制构造函数和赋值运算符:

    MyWindow(const MyWindow &) = delete;
    MyWindow &operator=(const MyWindow &) = delete;
    
    或者使类可移动且不可复制,以使其更易于使用

  • 范围守卫
  • 还有另一种选择:范围守卫。其思想是将清除代码放入局部变量的析构函数中

    这些局部变量通常是使用宏创建的。这就是我使用的:

    #include <exception>
    #include <utility>
    
    namespace Macro
    {
        template <typename T> class FinallyObject
        {
            T func;
    
          public:
            FinallyObject(T &&func) : func(std::move(func)) {}
            FinallyObject(const FinallyObject &) = delete;
            FinallyObject &operator=(const FinallyObject &) = delete;
            ~FinallyObject()
            {
                func();
            }
        };
    }
    
    #define FINALLY_impl_cat(a, b) FINALLY_impl_cat_(a, b)
    #define FINALLY_impl_cat_(a, b) a##b
    
    #define FINALLY(...) \
        ::Macro::FinallyObject FINALLY_impl_cat(_finally_object_,__LINE__) ([&]{ __VA_ARGS__ });
    
  • 在注释中建议,不要考虑在程序退出之前使用的资源。
  • 对于在程序退出之前使用的资源,则不需要进行清理。操作系统将自动清理它们。(
    SDL\u退出
    SDL\u销毁窗口
    等)


    一般来说,在使用SDL时,我们应该在什么时候提出异常?除非需要,否则通常避免使用它们是否被视为良好做法

    如果您正确地进行清理(使用析构函数和/或范围保护,而不是手动),异常将使这方面的工作变得更容易,而不是更困难


    在你真的投球之前,它们不会对你的表现产生太大的影响,所以如果你只在很少的情况下投球,你应该是很好的。但是它们确实增加了二进制文件的大小。

    您的进程正在消失,何必麻烦呢?内核对象/句柄将作为进程终止的一部分关闭。还有什么?在创建包装类时,您认为为SDL和SDL_IMG初始化创建一个包装类是个好主意吗(包装SDL环境初始化感觉有点奇怪)?@PremsupapongVanitcharenthum,这取决于您。在我看来没有错。
    int main(int, char **)
    {
        if (SDL_Init(...))
            /*throw or exit with an error*/;
        FINALLY( SDL_Quit(); )
    
        SDL_Window *window = SDL_CreateWindow(...);
        if (!window)
            /*throw or exit with an error*/;
        FINALLY( SDL_DestroyWindow(window); )
    
        // Your code here.
    }