【问题标题】:Why does delete only work in main and not in a function that gets as an input the object or objects to be deleted?为什么 delete 仅在 main 中起作用,而在将要删除的对象作为输入的函数中不起作用?
【发布时间】:2013-03-25 09:43:36
【问题描述】:

我正在尝试创建两个类,它们的实例一起创建和删除。一个类是另一个类的基础:

class Interface;

class MyClass
{
friend class Interface;
private:
  MyClass() {}
public:
  static MyClass *NewInstance();
  Interface *ControlPanel;
};

class Interface : public MyClass
{
friend class MyClass;
private:
  Interface() {}
public:
  void Control1() {cout << "control1" << endl;}
  void Control2() {cout << "control2" << endl;}
  void Control3() {cout << "control3" << endl;}
};

应该创建和删除实例的两个成员函数是:

MyClass *MyClass::NewInstance()
{
  MyClass *inst = new MyClass;
  inst->ControlPanel = new Interface;
  return inst;
}

void DeleteMyClassInstance(MyClass *inst)
{
  delete inst->ControlPanel;
  inst->ControlPanel = 0;
  delete inst;
  inst = 0;
}

我成功地将实例创建过程与创建实例的基类 (NewInstance()) 中的函数的使用联系起来。但是删除函数(DeleteMyClassInstance())不起作用(即调用函数后我仍然可以同时使用inst1inst1-&gt;ControlPanel):

int main()
{
  MyClass *inst1 = MyClass::NewInstance();

  inst1->ControlPanel->Control1();

  DeleteMyClassInstance(inst1);

  inst1->ControlPanel->Control1();

  return 0;
}

但是如果我将删除代码放在主函数中,它可以完美运行(删除语句之后的inst1-&gt;ControlPanel-&gt;Control1() 语句不起作用,这就是我想要的):

int main()
{
  MyClass *inst1 = MyClass::NewInstance();

  inst1->ControlPanel->Control1();

  delete inst->ControlPanel;
  inst->ControlPanel = 0;
  delete inst;
  inst = 0;

  inst1->ControlPanel->Control1();

  return 0;
}

我的问题是:为什么将 delete 语句直接放在 main 函数中起作用,而将它们放在单独的函数中并在 main 中使用它却不起作用?为什么我的DeleteMyClassInstance() 函数中的代码会被编译器忽略?

【问题讨论】:

  • 这听起来像是一个可怕的单例实现 - 不要这样做,如果您担心内存管理,请使用共享指针。
  • @TheForestAndtheTrees:在我看来,这与单身人士没有任何关系。通过多次调用NewInstance,可以创建任意数量的类实例。

标签: c++ class instantiation instances


【解决方案1】:

主要区别在于main函数中的代码inst=0main函数中的变量设置为null。使用DeleteMyInstance 中的代码,inst=0 行仅将DeleteMyInstance 中的局部变量设置为null(没用,因为在那之后它就不再使用了——启用更多警告并且您的编译器可能会提到它)。它不会影响main 中完全独立的同名变量。

所以,你的代码

DeleteMyClassInstance(inst1);
inst1->ControlPanel->Control1();

具有未定义的行为,因为您尝试使用已被删除的对象。 UB 意味着任何事情都可能发生。如果它看起来有效,那可能是因为在您的实现中,即使在 null(或其他无效)指针上调用函数 Control1 仍然“有效”,因为该函数不使用 this 或任何数据成员。但不应依赖该实现细节。

请注意(如果您还没有的话)您的代码显示了一些糟糕的 C++ 风格。您不应该编写特殊函数来删除您的类拥有的对象,这就是析构函数的用途。而且您不必在析构函数中显式删除对象,这就是智能指针的用途。而且您不应该在不需要时使用动态分配,这就是自动变量和数据成员的用途。一定要把这段代码弄好一次,作为一个学习练习在幕后发生的事情,但这应该是为了尽快正确地完成它。

【讨论】:

  • 谢谢。你对编码风格完全正确,但我只是想知道这是否可能。
【解决方案2】:

将您的 DeleteMyClassInstance 函数更改为。

void DeleteMyClassInstance(MyClass **inst)
{
  delete (*inst)->ControlPanel;
  (*inst)->ControlPanel = 0;
  delete (*inst);
  *inst = 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 2022-06-10
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    相关资源
    最近更新 更多