5

我刚刚遇到了一个类的构造函数需要分配内存的问题。于是我愉快地写了char *mem = static_cast<char*>(malloc(100*sizeof(*mem)));。但后来我突然意识到,如果出现错误,我无法返回错误代码(我的代码中没有使用异常)。我怎么解决这个问题?

我是否应该添加一个bool initialized成员,然后在我的课程之后,然后立即检查它,如:

myClass mc;
if (!mc.initialized) {
    printf("Memory allocation failed in mc's constructor\n");
    exit(1);
}

谢谢,博达赛多。

4

4 回答 4

10

您应该使用 new,而不是 malloc。当您内存不足时, new 会抛出 std::bad_alloc 。如果分配失败(或由于任何其他原因初始化有问题),则应从构造函数传播异常,因为这是阻止调用析构函数的唯一方法。如果构造函数成功完成,则必须调用析构函数(当然,除非它是堆分配的并且从未被释放)。

于 2010-07-05T01:55:21.350 回答
5

这就是发明异常的目的。另外,使用new代替malloc(3).

于 2010-07-05T01:52:39.703 回答
3

如果您不使用异常,则不应使用构造函数(或不应编写可能失败的构造函数),因为正如您所注意到的,除了通过异常之外,没有办法从构造函数报告错误。您可以交替使用工厂函数并使用它来将可能失败的位与不能失败的位分离

class myClass {
  private:
  char *m_malloced_buffer;

  // disallow calling ctors/dtors directly
  myClass(char *malloced_buffer) : m_malloced_buffer(malloced_buffer) {}
  ~myClass() { free(m_malloced_buffer); }

  public:
  static myClass *create()
  {
     char *buf = static_cast<char*>(malloc(100*sizeof(*mem)));
     if(!buf) return NULL;

     void *myClassRes = malloc(sizeof(myClass));
     if(!myClassRes) return NULL;
     new (myClassRes) myClass(buf); // placement new, uses existing memory to invoke the ctor
     return static_cast<myClass*>(myClassRes);
  }
  static void destroy(myClass* val)
  {
     if(!val) return;
     val->~myClass(); // explicitly invoke dtor
     free(val); // deallocate memory
  }
};
...
myClass *val = myClass::create();
if(val) { ... }
myClass::destroy(val);

在这个例子中,我使用 malloc 和 free 来完成所有的分配,你可以使用 new (std::nothrow) 和 delete 一样容易。您必须将每个可能失败的操作从 ctor 中提取到工厂函数中,以便您可以在不使用异常的情况下检查错误。即使在这个简单的例子中,你也可以看到这是一个巨大的颈部疼痛。你说你在评论中了解到“异常不是好的编码风格”,你的意思是你学到了(无论是通过有理由的论据和解释的指导,还是从经验中),还是有人说“异常不是好的编码风格”和你已经接受了作为教条的声明?

使用 bool 初始化成员会导致僵尸对象问题(请参阅http://www.parashift.com/c++-faq-lite/exceptions.html)。

于 2010-07-05T02:21:51.303 回答
2

如果您使用的是 C++ 而不是 C,那么您可能应该使用 new 而不是 malloc。抛出异常可能是您想要在构造函数中执行的操作。

如果您因为不想要异常而使用 new (nothrow),或者您正在使用 malloc,那么您可以简单地测试为 NULL 返回的指针。然后,您将设置一个成员变量,指示该对象处于失败状态。这可以在标准 C++ 库的流类中看到。

于 2010-07-05T01:52:50.980 回答