在C++中,何时使用"new"和何时不使用?

128

可能重复:
何时应在C++中使用new关键字?

在C++中何时应该使用"new"运算符?我来自于C# / Java背景,实例化对象对我来说很困惑。

如果我已经创建了一个简单的名为"Point"的类,那么创建点时,我应该:

Point p1 = Point(0,0);

或者
Point* p1 = new Point(0, 0);

有人能为我澄清何时使用new运算符,何时不使用吗?

重复:

在C++中何时应该使用new关键字?

相关:

关于自定义对象的构造函数/析构函数和C++中的new/delete运算符

在C++中正确使用堆栈和堆的方法?


重复 - 太多次无法计数 - anon
正如Neil所说,这个问题已经被问了无数次。 - Naveen
4个回答

184

当您希望一个对象一直存在,直到您使用delete将其销毁时,应使用new。如果您不使用new,则该对象将在超出范围时被销毁。以下是一些示例:

void foo()
{
  Point p = Point(0,0);
} // p is now destroyed.

for (...)
{
  Point p = Point(0,0);
} // p is destroyed after each loop

有些人会说使用new决定了你的对象是在堆上还是栈上,但这仅适用于在函数内声明的变量。

在下面的示例中,变量'p'的位置将位于其包含对象Foo的分配位置。我更喜欢称之为“原地”分配。

class Foo
{

  Point p;
}; // p will be automatically destroyed when foo is.

使用new分配(和释放)对象比在原地分配要昂贵得多,因此应该限制其使用仅用于必要的情况。

第二个需要使用new分配的例子是数组。您无法在运行时更改就地或堆栈数组的大小,因此如果需要一个大小未确定的数组,则必须通过new进行分配。

例如:

void foo(int size)
{
   Point* pointArray = new Point[size];
   ...
   delete [] pointArray;
}

(*提前挑刺 - 是的,有一些扩展可以允许变量大小的堆栈分配)。


2
+1 请记住,您需要手动删除 new 出来的指针delete p1; - Gregor Brandt
7
+1 很好。只需记住第一个可以写成 Point p(0, 0);。使用 = .. 语法可能会让他认为 p 是某种指针被赋值了。 - Johannes Schaub - litb
2
@Andrew Grant 如果你必须使用 new,请使用在 C++11 STL <memory> 中引入的 shared_ptrunique_ptr。共享指针将自动进行删除的簿记。请注意,对于数组,由 shared_ptr 提供的默认删除器调用的是 delete 而不是 delete[],因此请使用 lambda 函数。std::shared_ptr<int> p(new int[10], [](int* p) { delete[] p; });或者std::shared_ptr<int> p(new int[10], std::default_delete<int[]>());或者使用 unique_ptr 提供的帮助程序来调用 delete[]std::unique_ptr<int,void(*)(int*)> p(new int[10], [](int* p) { delete[] p; }); - katta
这个回答已经超过10年了。现在不应该是“在RAII和智能指针之间永远不需要使用`new'”吗? - Victor Eijkhout

13

请看这个问题这个问题,它们提供了关于C++对象实例化的好答案。

基本想法是,在堆上(使用new)实例化的对象需要手动清理,而在栈上(不使用new)实例化的对象会在超出作用域时自动清理。

void SomeFunc()
{
    Point p1 = Point(0,0);
} // p1 is automatically freed

void SomeFunc2()
{
    Point *p1 = new Point(0,0);
    delete p1; // p1 is leaked unless it gets deleted
}

4

当你想要在堆上创建一个对象而不是栈上时,应该使用new。这允许通过指针从当前函数或过程之外访问对象。

如果您在其他语言中没有接触过指针和内存管理,那么查找C++中的指针和内存管理可能对您有用。


1
使用 new 操作符并不保证堆分配,仅仅避免使用 new 也不能保证栈分配。 - Michael J. Gray

3
新建(New)通常用于分配动态内存,然后必须释放该内存。通过采用第一种选项,该内存将在作用域丢失时自动释放。
Point p1 = Point(0,0); //This is if you want to be safe and don't want to keep the memory outside this function.

Point* p2 = new Point(0, 0); //This must be freed manually. with...
delete p2;

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