C++指针对象与非指针对象

18

可能是重复问题:
为什么你会想要在堆上分配内存而不是栈上?

Test2 *t2 = new Test2();
t2->test();

Test2 t3;
t3.test();
为什么我要创建一个Test2类型的指针对象?为什么不只使用非指针版本的Test2?为什么我要使用指针对象?
找到答案在这里:

1
许多重复的内容,其中第一个是(来自Firas Assaad的答案)https://dev59.com/V3I_5IYBdhLWcg3wDOhC - David Rodríguez - dribeas
1
我现在意识到了。然而,提出问题是困难的部分。现在我想我明白了... :D - anon235370
7个回答

21

使用动态存储的原因包括(但可能不限于):

  1. 手动控制对象的生命周期 - 只有在你明确销毁该对象时,它才会存在
  2. 在运行时创建所需数量的对象,当最终对象数量仅在运行时才能确定时(如树中的节点数或数组中的元素数)。
  3. 在运行时控制对象的类型(例如多态对象的实际类型)。

当没有区别时,最好使用您的 t3 方法创建对象。除非必须,否则不要使用动态内存。但有时您确实需要使用它(请参见上述原因)。


7
如果您需要使一个对象在其创建的范围之外仍然存在,那么解决方案之一就是将其创建在堆上。在这种情况下,您需要一个指针。还有其他原因,但这是最常见的原因。
使用指针的另一个原因是用于“out”参数。虽然可以使用引用,但许多人更喜欢使用指针,因为它可以省去在调用现场修改参数的步骤。foo(var); vs foo(&var); 此外,指针可用于传递或返回可能存在或不存在的对象。例如:T *foo(); // 返回指向对象或NULL的指针
实际上,列表还有很多其他用途。

你能列举一些其他的原因吗? - anon235370
1
不是真的。在局部作用域中声明为 static Test2 t3; 的对象将超出其创建的范围。但它并没有在堆上创建。 - AnT stands with Russia
@AndreT:好观点,我会修改我的回答。 - Evan Teran

4

如果您有一个非常大的对象(例如具有非常大的缓冲区成员的对象),您可能不想在堆栈上分配它,因为堆栈空间是有限的,在这种情况下,您可以使用operator new在堆上进行分配。


谢谢您;我是一名Java和C++程序员,但我的课程从未涉及堆栈/堆... - anon235370


3
任何类型的动态数据结构(如列表、二叉树、堆栈等)都必须使用对象指针。

2

主要区别在于它们存在内存中的位置。"非指针版本"存在于栈上,这意味着一旦函数返回,它将无效,而"指针版本"存在于堆上,这意味着它将一直存在,直到有人调用delete。通常情况下,最好的做法是尽可能将对象放在栈上,只有在需要时才放在堆上。需要将对象放在堆上的一个很好的例子是:

Obj* f()
{
  return new Obj();
}

new Obj()会在堆上创建一个Obj对象,并返回指向它的指针,然后从函数中返回。

例如,这样是不起作用的。

Obj* f()
{
  Obj o1;
  return &o1;  //BAD!!
}

由于指针值&o1引用堆栈上的内存,并且在该点上已清除堆栈上的f()函数,因此谁知道会发生什么。绝对不会有好事情发生。


1
一个常见(但不是必需的)实现是将局部变量分配在堆栈上。堆栈是有限的,可能会出现对象过大而无法在堆栈上分配的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接