如何将C ++对象实例化?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (28)

我是一位试图理解C ++的C程序员。许多教程使用片段展示对象实例化,例如:

Dog* sparky = new Dog();

这意味着你稍后会做:

delete sparky;

这是有道理的。现在,在不需要动态内存分配的情况下,是否有任何理由使用上述而不是

Dog sparky;

并让一旦闪烁超出范围调用析构函数?

提问于
用户回答回答于

相反,你应该始终更喜欢堆栈分配,在一定程度上,你绝不应该在用户代码中添加新的/删除。

正如你所说,当变量在堆栈中被声明时,它的析构函数会在超出范围时被自动调用,这是跟踪资源生命周期并避免泄漏的主要工具。

因此,一般来说,每次需要分配资源时,无论是内存(通过调用new),文件句柄,套接字还是其他任何东西,都将其包装在构造函数获取资源的类中,然后析构函数释放它。然后,您可以在堆栈中创建该类型的对象,并确保你的资源在超出范围时被释放。这样你就不必在任何地方跟踪你的新/删除对,以确保你避免了内存泄漏。

RAII

还要研究智能指针类,这些智能指针类用于在极少数情况下包装所产生的指针,当您必须在专用的RAII对象外分配新的东西。您将指针传递给一个智能指针,智能指针随后通过引用计数跟踪其生存期,并在最后一个引用超出范围时调用析构函数。标准库具有std::unique_ptr简单的基于范围的管理,并std::shared_ptr通过引用计数来实现共享所有权。

用户回答回答于

尽管在分配和自动释放事物方面可能有优势,但它有一些缺点。

  1. 你可能不想在堆栈上分配巨大的对象。
  2. 运行时类型!考虑这个代码:
#include <iostream>

class A {
public:
  virtual void f();
};

class B : public A {
public:
  virtual void f();
};

void A::f() {cout << "A\n";}
void B::f() {cout << "B\n";}

int main(void) {
  A *a = new B();
  a->f();
  delete a;
  return 0;
}

它显然会打印“B \ n”。现在让我们看看使用堆栈时会发生什么:

int main(void) {
  A a = B();
  a->f();
  return 0;
}

它会(对于C ++的人而言)显示“A \ n”。对于那些与Java或其他OOP风格语言类似的人来说,这可能并不直观。原因是,你没有B的实例上的指针。但是创建了一个B的实例,然后将其复制到A的一个实例(隐式地新创建)。

扫码关注云+社区