安全数组删除

lit*_*net 7 c++ arrays

我是C++的新手,我并不完全确定如何以安全的方式处理数组和指针.在我的班上,我有一个叫做项目的成员:

Item * items;
Run Code Online (Sandbox Code Playgroud)

在我的类方法read()中我打开一个文件并从这个文件中读取项目.我相应地分配空间:

items = new Item[item_count];
Run Code Online (Sandbox Code Playgroud)

item_count作为文件中的变量给出,并在创建任何项目之前预先读取.在我班级的解构器中,我再次释放这样的内存:

delete[] items;
Run Code Online (Sandbox Code Playgroud)

但是如果我read()在执行解构函数之前调用该方法两次,则第一个数组的内存将无法正确释放.我想在分配新内存之前事先在read方法中释放它.但是如何检查是否已为阵列分配了一些内存items

编辑:我知道还有很多其他的可能性,更多的"现代"方法和更舒适的解决方案.但在这种情况下,我们明确告诉使用指针和数组(仅限教育目的).

Dre*_*ann 8

在现代C++中,"安全的方法"是完全避免原始指针和原始数组.

像这样声明你的变量:

std::vector<Item> items;
Run Code Online (Sandbox Code Playgroud)

像这样分配空间:

items.resize(item_count);
Run Code Online (Sandbox Code Playgroud)

在类的解构函数中,不需要代码来释放此内存.它是自动处理的.

items您在问题中描述的重复使用将起作用.

  • @iharob这是正确的,如果我正确地按照你的比喻.总的来说,如何安全驾驶汽车问题太过广泛.首先,这里从不需要汽车. (3认同)

Mr.*_*C64 6

除非你有充分的理由不这样做,否则只需std::vector在C++中使用数组:

#include <vector>  // for std::vector

....
std::vector<Item> items;
Run Code Online (Sandbox Code Playgroud)

这样,您就不必显式调用delete[]释放矢量项的资源; 由于vector(和Items')的析构函数,它只是自动完成.

这有助于构建在结构上无法泄漏资源的代码.


您可以使用以下内容创建矢量itemCount Items:

std::vector<Item> items(itemCount);
Run Code Online (Sandbox Code Playgroud)

或者您可以使用其resize()方法动态调整向量的大小,例如:

items.resize(itemCount);
Run Code Online (Sandbox Code Playgroud)

  • @iharob:你还在C++ 98模式吗?`... <Item >>`语法在**C++ 11/14中完全有效.** (5认同)
  • @ iharob,如果你不喜欢C++那么你为什么回答并评论有关它的问题? (4认同)
  • @iharob:OP在他的请求中可能更具体一点(事实上,我也写过"除非你有一些强烈的理由不这样做").无论如何,OP的项目是一个可移动的类是足够的; 或者他可以使用`vector <unique_ptr <Item >>`. (3认同)

Iha*_*imi 2

在c中,通常将指针初始化为NULL,以便检查它是否指向有效内存,然后在释放后立即将其设置回NULL

如果不这样做,可能会导致问题,例如取消引用已经释放的指针(它们称为悬空指针),因此您必须小心。

在 c++ 中,您应该使用nullptr与 c 等效的NULL.

另外,C++ 中有智能指针,即可以自动执行此操作的指针。

编辑:(上面的答案已编辑)根据评论的建议,虽然同样的想法是正确的,但您不应该NULL在 c++ 中使用,而是使用nullptr具有相同功能的,但要注意在 c++ 中void *不会自动使用转换为任何其他指针类型,如 c 中的指针类型。

这个Stack Overflow 答案有详细信息,还有一个肯定会说服你和我使用的示例nullptr

  • 强烈建议不要使用“NULL”。`nullptr` 更好。更好的是使用“unique_ptr”而不用担心任何事情。 (8认同)
  • 好吧,至少你没有表现出有害的固执。也不知道关于 C 的“语言战争”从何而来?您被否决是因为您的建议过时且危险。试着记住我们为什么在这里。 (5认同)
  • 顺便说一句,这完全是无稽之谈:_“c++ 语言引入了新的东西,这打破了它与 c 100% 兼容的初衷。”_ (4认同)
  • 我不知道区别,我对此不感兴趣,我的答案中的想法是正确的,如何在 C++ 中实现这一点是另一回事,我将我的答案限制在问题上,无论是“NULL”还是“nullptr”在我看来,这似乎是一个不必要的构造,即使我不知道它是什么意思,但如果它是 c++ 方式,你可以像你所做的那样留下评论,以便 OP 可以遵循它。这是c++语言引入了新的东西,这超出了它与c 100%兼容的初衷。 (2认同)
  • @iharob 只是注意到“NULL”不是“void *”。这正是 C++ 中的“#define NULL 0”。问题是,如果一个函数有一个 int 和指针重载,它会调用 int 函数,即使您期望指针 1 代表“NULL”。`nullptr` 是一个指针类型,而不是宏,并修复了它。 (2认同)