17

这是我的一本书中的一个问题(没有附加答案),我已经思考了几天了。答案仅仅是因为 C++ 代码最终会崩溃,因为它在每次迭代后都会创建一个垃圾内存单元吗?

考虑以下 Java 和 C++ 代码片段,它们是基于 GUI 的应用程序的两个版本的一部分,它收集用户偏好并使用它们来组装命令及其参数。方法/函数 getUserCommandSpecification() 返回一个表示命令代码及其参数的字符串。返回的字符串用于构建所需的命令,然后执行该命令。

假设如下:

(i) 在 Command 对象的 while 循环中创建后(在 Java 情况下由 cmd 引用或在 C++ 情况下由 cmd 指向),不再引用或使用指向生成对象的引用/指针 cmd。

(ii) 应用程序还定义了一个类 Command 及其方法/函数 execute()。

一种。下面详述的两个代码版本中的哪一个最终会崩溃。
湾。解释为什么一个程序版本崩溃而另一个没有崩溃。

Java 代码

...
while (true) {
   String commandSpecification = getUserCommandSpecification();
   Command cmd = new Command(commandSpecification);
   cmd.execute();
}
...

C++ 代码

...
while (true) {
   string commandSpecification = getUserCommandSpecification();
   Command* cmd = new Command(commandSpecification);
   cmd -> execute();
}
...
4

8 回答 8

45

是的,C++ 版本由于new Command(...)没有delete. 当然,它可以很容易地进行不同的编码以避免这种情况:

...
while (true) {
   string commandSpecification = getUserCommandSpecification();
   Command cmd(commandSpecification);
   cmd.execute();
}
...

...所以我不确定这个例子是否像他们想象的那样具有启发性。

于 2012-11-12T04:24:32.490 回答
18

C++ 代码创建了无数个Command永远不会被删除的对象。在 C++ 中没有垃圾收集。必须调用deletenew.

于 2012-11-12T04:24:28.543 回答
13

使用原始指针已经过时了。正如已经指出的那样,这里是不必要的。如果实际需要指针,请使用 std::unique_ptr。

while (true) {
   string commandSpecification = getUserCommandSpecification();
   std::unique_ptr<Command> cmd(new Command(commandSpecification));
   cmd -> execute();
}

这里没有内存泄漏。

于 2012-11-12T05:45:31.167 回答
6

C++ 示例将由于内存泄漏而崩溃。

Command* cmd = new Command(commandSpecification);

被连续调用,没有对应的delete.

于 2012-11-12T04:25:14.987 回答
6

在 C++ 中,没有垃圾收集(范围内的本地人除外)。因此,C++ 不断地Command在堆上分配对象,而无需通过调用delete. 因此,C++ 程序最终会耗尽内存。

在 Java 中,垃圾收集器将看到堆上的对象不再被引用并释放它们,从而避免内存不足错误。

于 2012-11-12T04:26:31.480 回答
4

AFAIK,在 C++ 中,您需要显式销毁您创建的对象(使用new关键字),而在 Java 中,垃圾收集器(帮助回收不再可访问的对象占用的内存)为您处理它。

在 Java 中,以这种方式创建的对象会增加次要 GC 的频率,因此这些对象甚至可能不会到达堆中的老年代区域(取决于execute运行的时间)。

使用 Java 实现极致性能

于 2012-11-12T04:25:01.417 回答
1

由于尚未明确说明(搜索页面中的单词没有匹配项),我觉得最好补充一下:C++ 代码中有一个明显的内存泄漏错误

这是另一种可行的替代方法,使用std::auto_ptr(Boostboost::scoped_ptr或 QtQScopedPointer是替代智能指针):

while (true) {
   string commandSpecification = getUserCommandSpecification();
   std::auto_ptr<Command> cmd(new Command(commandSpecification));
   cmd->execute();
}
于 2012-11-13T20:56:43.800 回答
0

阅读 Java 中的垃圾收集。在 java 中,您不需要手动删除对象,因为 jvm 会自动为您执行此操作,但在 c++ 中,您需要删除您不需要的对象。垃圾收集器也是 java 中的一个功能强大的工具,如果您需要帮助,您可以在工作完成后将对象引用为 null。

Object x=new Object()
///
.
.
.
you did your works
x=null;
于 2012-11-12T12:15:26.290 回答