我正在尝试使用C++和SDL编写一个简单的游戏。我的问题是,存储类成员变量的最佳实践是什么。

MyObject obj;
MyObject* obj;

我读了很多关于在类似问题中尽可能消除指针的知识,但是我记得几年前我读过一些书,他们经常使用它(对于所有非平凡的对象)。另一件事是SDL在其许多功能中返回了指针,因此在使用SDL对象时,我将不得不大量使用“*”。

当我认为使用除默认构造函数之外的其他方法初始化第一个方法的唯一方法是通过初始化列表时,我是否正确?

最佳答案

首先,我想说我完全同意DietmarKühl和Mats Petersson的回答。但是,您还必须考虑到SDL是纯C库,其中大多数API函数都期望结构的C指针可以拥有大量数据。因此,您不应在堆栈上分配它们(应使用new运算符在堆上分配它们)。此外,由于C语言不包含智能指针,因此在将其发送到SDL API函数之前,您需要使用std::unique_ptr::get()恢复std::unique_ptr拥有的C指针。这可能非常危险,因为必须确保在SDL使用C指针时std::unique_ptr不会超出范围(与std::share_ptr类似的问题)。否则,您会遇到段错误,因为std::unique_ptr将在SDL使用它时删除C指针。

每当您需要在C++程序中调用纯C库时,建议您使用RAII。主要思想是创建一个小的包装类,该包装类拥有C指针,还为您调用SDL API函数。然后,使用类析构函数删除所有C指针。

例:

class  SDLAudioWrap {
  public:
  SDLAudioWrap() { // constructor
     // allocate SDL_AudioSpec
  }
  ~SDLAudioWrap() { // destructor
     // free SDL_AudioSpec
  }

  // here you wrap all SDL API functions that involve
  // SDL_AudioSpec and that you will use in your program
  // It is quite simple
  void SDL_do_some_stuff() {
    SDL_do_some_stuff(ptr); // original C function
                            // SDL_do_some_stuff(SDL_AudioSpec* ptr)
  }
  private:
  SDL_AudioSpec* ptr;
}

现在,您的程序具有异常安全性,并且不会出现在SDL使用它的情况下让智能指针删除C指针的问题。

更新1:我忘记提及了,因为SDL是C库,因此您将需要一个自定义删除程序类,以便使用智能指针正确管理其C结构。

具体示例:GSL GNU科学库。集成例程需要分配一个名为“gsl_integration_workspace”的结构。在这种情况下,您可以使用以下代码来确保您的代码是异常安全的
 auto deleter= [](gsl_integration_workspace* ptr) {
   gsl_integration_workspace_free(ptr);
 };
 std::unique_ptr<gsl_integration_workspace, decltype(deleter)> ptr4 (
 gsl_integration_workspace_alloc (2000), deleter);

我更喜欢包装器类的另一个原因

关于c++ - 如何在C++中存储类成员对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18522382/

10-15 00:24