我一直在使用C++很短的一段时间,我一直想知道的 新的 关键词。简单地说,我应该使用它,或者没有?

1) 新的 关键字...

MyClass* myClass = new MyClass();
myClass->MyField = "Hello world!";

2)没有 新的 关键字...

MyClass myClass;
myClass.MyField = "Hello world!";

从实施的角度看,他们似乎并不认同(但是我敢肯定他们都)...然而,我的主要语言,当然,第1方法是什么我用的。

难度似乎是,方法1是难以使用与性病C++类。

这方法我应该使用?

更新1:

我最近使用过的 新的 关键字 存储器(或 免费存储)对于大型阵列,这是出去的范围(即正在返回一个功能)。在哪里之前我是用于堆叠,造成一半的元素是腐败之外的范围,切换到堆使用保证的要素都是在老练。耶!

更新2:

我的一个朋友最近告诉我有一个简单的规则的使用 new 关键词;每一次你的类型 new, 、类型 delete.

Foobar *foobar = new Foobar();
delete foobar; // TODO: Move this to the right place.

这有助于防止存储器的泄漏,因为你总是有把删除的地方(即当你剪切和粘贴到任何一个析构或其他行为)。

有帮助吗?

解决方案

方法1(使用 new)

  • 存储器将分配的上的对象 免费存储 (这往往是同样的事情的 )
  • 你需要明确 delete 你的对象后面。(如果你不要删除它,您可以创建一个存储器泄漏)
  • 存储器停留直到你分配的 delete 它。(即你可以 return 一个目的,你创建的使用 new)
  • 例如在的问题 泄漏的记忆 除非另有所指 deleted;和它 应该始终被删除, 无论其控制的路径是采取,或者如果例外抛出。

方法2(未使用 new)

  • 存储器将分配的上的对象 (在所有地方的变量去)通常不存储器可用于堆;如果你分配了太多的对象,你的风险堆溢出。
  • 你不需要 delete 它以后。
  • 记忆不再分配给它的时超出范围。(即你不应该 return 指向一个目的堆)

尽这一使用;你选择的方法最适合你,给予上述的限制。

一些简单的情况下:

  • 如果你不想担心呼唤 delete, ,(并可能导致 存储器泄漏)你就不该用 new.
  • 如果你愿意返回一个指向你的对象,从一个功能,则必须使用 new

其他提示

有两者之间的重要区别。

new分配的一切行为很像在C#中的值类型(人们通常会说,这些对象被分配在栈,这可能是最常见的/明显的情况下,但并非总是如此。更准确地说,对象,而不分配使用new自动存储持续时间new分配一切都在C#在堆上分配,并且返回一个指向它的指针,酷似引用类型。

在栈上分配任何必须具有一定的大小,在编译时(编译器必须正确地设置堆栈指针,或者如果对象是另一个类的成员,其具有调整的所述大小来确定其他类)。这就是为什么在C#中的数组是引用类型。他们必须的,因为引用类型,我们可以在运行时有多少内存,要求决定。而同样适用于这里。只有具有恒定大小(可以在编译时被确定的尺寸)的阵列可以与自动存储持续时间(在堆)进行分配。动态大小的数组已在堆上分配,通过调用new

(而这正是任何相似C#停止)

现在,在栈上分配的任何具有“自动”存储时间(实际上你可以将变量声明为auto,但是这是默认的,如果没有指定其他存储类型,这样的关键字是不是真正在实践中使用,但这是来自何处)

自动存储持续时间意味着正是这听起来像,可变的持续时间被自动处理。相比之下,在堆上分配任何必须由你手动删除。 下面是一个例子:

void foo() {
  bar b;
  bar* b2 = new bar();
}

此函数创建三个值值得考虑:

在第1行,它声明类型b的可变bar堆栈(自动持续时间)。

在第2行,它声明堆栈(自动持续时间),并在bar指针b2 调用新,在堆上分配一个bar对象。 (动态持续时间)

当函数返回时,将发生以下情况: 首先,b2超出范围(破坏的顺序总是的结构的顺序相反)。但是b2只是一个指针,所以什么也没发生,它所占用的内存仅仅是释放。并且重要的是,存储器它指向(在堆上的bar实例)未被触摸。只有指针被释放,因为只有指针有自动的持续时间。 第二,b超出范围,因此,因为其具有自动持续时间,它的析构函数被调用,并且该存储器被释放。

和堆上的barinstance?它可能仍然存在。没有人费心去删除它,所以我们已经泄漏的内存。

从这个例子中,我们可以看到自动持续时间,任何事情都是的保证的有它的析构函数调用时它超出范围。这是有用的。但在堆上分配什么,只要我们需要它,并可以动态调整大小,在数组的情况持续。这也是有用的。我们可以用它来管理我们的内存分配。如果Foo类分配在其构造堆一些内存,并在其析构函数删除的记忆。然后,我们可以得到两全其美,安全的内存分配,保证被再次释放,但不强迫一切是在堆栈上的限制。

这是相当多的大多数C ++代码是如何工作的。 看看标准库的std::vector例如。这通常是在栈中分配,但可以动态调整和调整大小。它通过对堆根据需要在内部分配内存做到这一点。类的用户看不到这一点,所以有”S无泄漏内存,或忘记清理你分配什么样的机会。

此原理被称为RAII(资源获得是初始化),它可以扩展到必须获取和释放的任何资源。 (网络套接字,文件,数据库连接,同步锁)。所有这些都可以在构造函数中获得的,并在析构函数中释放出来,所以你保证你获得的所有资源将得到重新释放。

作为一般规则,从来没有使用新的/直接从您的高级代码删除。始终把它包在可管理的内存给你一个类,这将确保它得到重新释放。 (是的,有可能是此规则的例外,特别是智能指针要求你直接调用new,以及指针传递给它的构造,然后接管并确保delete正确调用。但是,这仍然是一个非常重要的规则拇指)

  

应该使用哪种方法?

这是几乎从来没有在你输入偏好,但根据上下文确定。如果您需要保留该对象横跨几堆,或者如果它是为你分配它的自由存储堆栈太重。此外,由于你分配一个对象,你也负责释放内存。查找的delete运算符。

要缓解使用空闲存储管理人员的负担已经发明的东西一样auto_ptrunique_ptr。我强烈建议你看看这些。他们甚至可能会帮上你的打字问题; - )

如果你在写C ++,你很可能编写性能。使用新的,自由存储区比使用堆栈(尤其是在使用线程时),因此只在需要时使用它要慢得多。

正如其他人所说,你需要当你的对象需要的功能外居住或对象的范围新的,对象是真正的大或当你不知道在编译时数组的大小。

另外,尽量避免使用过删除。包装你的新成智能指针来代替。让智能指针调用删除你。

有某些情况下,智能指针不是聪明。绝不会存储的std :: auto_ptr的<>一STL容器的内部。这将过快删除,因为容器内的复制操作的指针。另一种情况是,当你有一个指针的对象一个真正的大STL容器。提高:: shared_ptr的<>将有一吨的速度开销,因为它对颠簸的引用计数上下。更好的方法在这种情况下走的是把STL容器到另一个对象,并给该对象析构函数,将调用删除容器中的每一个指针。

在简短的回答是:如果你在C ++初学者,你应该的从不的是使用newdelete自己

相反,应该使用智能指针如std::unique_ptrstd::make_unique(或较少,std::shared_ptrstd::make_shared)。这样,你就不必担心内存泄漏几乎一样多。而且,即使你是更先进的,最好的做法通常是封装你使用newdelete成小类(如自定义智能指针),这只是专用于对象生命周期问题的定制方式。

当然,在幕后,这些智能指针仍然使用他们仍然具有相关联的运行时开销执行动态分配和释放,所以代码。这里其他的答案已经涵盖了这些问题,以及如何在何时使用智能指针而不只是在栈上创建对象或将它们作为一个对象的直接成员,不够好,我就不重复了设计决策。但我的执行摘要将是:不要使用智能指针或动态分配,直到东西迫使你

如果没有new关键字你存储在调用堆栈。在堆栈中存储过大的变量会导致堆栈溢出

如果您的变量只在一个单一功能的情况下使用,你最好使用堆栈变量,即选项2正如其他人所说,你不必来管理堆栈变量的生命周期 - 他们被构造和自动破坏。而且,分配/在堆上解除分配的变量是通过比较慢。如果你的函数被调用往往不够,你会看到,如果使用堆栈变量对堆变量巨大的性能提升。

也就是说,有一对夫妇,其中堆栈变量是不够的。

明显实例

如果在堆栈变量具有大的内存占用,然后运行溢出堆栈的风险。默认情况下,每个线程的堆栈大小为1 MB 在Windows上。这是不可能的,你将创建一个堆栈变量大小为1 MB,但你必须记住,堆栈的使用是累积的。如果你的函数调用它调用它调用另一个函数......,所有这些功能的堆栈变量占用空间相同的堆栈上其他功能的功能。递归函数可以根据递归有多深,快碰到这个问题。如果这是一个问题,可以提高堆叠(不推荐)的尺寸或分配上使用新的操作者堆变量(推荐)。

另外,更有可能的条件是,你的变量需要“活”超越你的函数的范围。在这种情况下,你在堆上分配变量,以便它可以在任何给定功能的范围之外到达。

您传递myClass的一个功能,还是希望它是功能之外存在吗?正如一些人所说,这是所有关于范围时,你是不是在堆中分配。当你离开的功能,它消失了(最终)。一个初学者提出的典型的错误是在一个函数来创建一些类的局部对象,并没有在堆中分配它返回它的尝试。我还记得我在前面几天的调试这种事情回来做C ++。

在简单的答案是肯定的 - 新的()在堆上创建一个对象(即你必须显式调用删除它来管理它的寿命(不幸的副作用),而第二种形式在栈中创建一个对象在当前的范围和该对象时,它超出范围将被破坏。

在简短的回答是肯定的“新”的关键字是当你使用它的对象数据存储上,而不是堆栈,这是最重要的堆非常重要!

在第二方法创建堆栈上的情况下,用这样的事情的东西声明int并被传递到函数的参数的列表一起。

第一种方法使空间用于指针堆栈,您已设置到一个新的MyClass已经在堆上分配在存储器中的位置上 - 或自由存储

第一种方法还要求您delete创建具有new什么,而在第二种方法中,类会自动破坏和释放时,它超出范围(下一闭括号,通常情况下)。

scroll top