c++ - 为什么不在 C++ 中对所有内容都使用指针?

标签 c++ pointers heap-memory stack-memory

假设我定义了一些类:

class Pixel {
    public:
      Pixel(){ x=0; y=0;};
      int x;
      int y;
}

然后使用它编写一些代码。我为什么要这样做?

Pixel p;
p.x = 2;
p.y = 5;

来 self 经常写作的 Java 世界:

Pixel* p = new Pixel();
p->x = 2;
p->y = 5;

他们基本上做同样的事情,对吧? 一个在堆栈上,另一个在堆上,所以我必须稍后将其删除。两者有什么根本区别吗?为什么我应该更喜欢其中一个?

最佳答案

是的,一个在堆栈上,另一个在堆上。有两个重要的区别:

  • 首先,显而易见但不太重要的一点是:堆分配速度很慢。堆栈分配很快。
  • 其次,更重要的是RAII .因为堆栈分配的版本会自动清理,所以它很有用。它的析构函数会被自动调用,这使您可以保证该类分配的任何资源都被清理干净。这本质上是避免 C++ 中的内存泄漏的方法。您可以通过自己从不调用 delete 来避免它们,而是将其包装在堆栈分配的对象中,这些对象在内部调用 delete,通常在它们的析构函数中。如果您尝试手动跟踪所有分配,并在正确的时间调用 delete,我保证每 100 行代码至少会有一次内存泄漏。

作为一个小例子,考虑以下代码:

class Pixel {
public:
  Pixel(){ x=0; y=0;};
  int x;
  int y;
};

void foo() {
  Pixel* p = new Pixel();
  p->x = 2;
  p->y = 5;

  bar();

  delete p;
}

相当无辜的代码,对吧?我们创建一个像素,然后调用一些不相关的函数,然后删除该像素。有内存泄漏吗?

答案是“可能”。如果 bar 抛出异常会发生什么? delete 永远不会被调用,像素永远不会被删除,并且我们会泄漏内存。现在考虑一下:

void foo() {
  Pixel p;
  p.x = 2;
  p.y = 5;

  bar();
}

这不会泄漏内存。当然,在这个简单的例子中,所有东西都在堆栈上,所以它会自动清理,但即使 Pixel 类在内部进行了动态分配,也不会泄漏。 Pixel 类将被简单地赋予一个删除它的析构函数,并且无论我们如何离开 foo 函数都会调用这个析构函数。即使我们因为 bar 抛出异常而离开它。以下稍微做作的示例显示了这一点:

class Pixel {
public:
  Pixel(){ x=new int(0); y=new int(0);};
  int* x;
  int* y;

  ~Pixel() {
    delete x;
    delete y;
  }
};

void foo() {
  Pixel p;
  *p.x = 2;
  *p.y = 5;

  bar();
}

Pixel 类现在在内部分配了一些堆内存,但它的析构函数负责清理它,所以当使用这个类时,我们不必担心它。 (我可能应该提到,这里的最后一个例子被简化了很多,以显示一般原理。如果我们要实际使用这个类,它也包含几个可能的错误。如果 y 的分配失败,x 永远不会被释放,如果 Pixel 被复制,我们最终会导致两个实例都试图删除相同的数据。因此,这里的最后一个例子有点不可信。实际代码有点棘手,但它显示了一般的想法)

当然,同样的技术可以扩展到内存分配以外的其他资源。例如,它可用于保证文件或数据库连接在使用后关闭,或者线程代码的同步锁被释放。

关于c++ - 为什么不在 C++ 中对所有内容都使用指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1064325/

相关文章:

c++替换调用对象方法的宏函数

c - 在C语言中,带有两个星号(**)的变量声明是什么意思?

delphi - ((指针)(P)+1)^什么时候可以起作用?

java - 如何增加 JVM 堆大小

android - OpenCV无法为ARM64目标构建(Android)

c++ - wxWidgets BoxSizer 没有扩展到全宽

c++ - 使用英特尔线程构建模块 : error operands to ? 进行编译:

c++ - 如何获得指向虚拟成员函数的 "direct"函数指针?

C++堆组织——哪种数据结构?

java - Java 守护线程是否与生成进程共享堆或 Perm Gen?