5

这是作业的一部分,但我只是要求澄清:

当程序启动时,从 ATM.txt 加载数据并将它们存储在动态数组(ATM 类型,而不是 STL)中。

在没有 STL 的情况下,我究竟如何做动态数组?我想也许分配意味着使用指针,“ATM 类型”让我失望。

再次提到:

将 accounts.txt 文件放入动态数组(帐户类型,而不是 STL)

--不是作业的一部分

我从来不理解内存不安全操作的使用,例如从第一行提取文件中的项目数:

例如。

5
abc
def
hij
kml
mno

使用 STL(向量或 C++11 数组)而不依赖文件中的数字会不会更聪明,因为它可能不准确导致缓冲区溢出等?

//Edit 在文件 Account.h 中定义一个类 Account,其中包含数据成员:客户 id、BSB 编号等。

我假设 Account 和 ATM 类型就是这些类。

4

5 回答 5

4

动态数组的最基本形式是使用创建new[]和销毁使用delete[]

ATM * atms = new ATM[count];
// do stuff with the array
delete [] atms;

但是,这带来了使用数组的代码可能会引发异常、从函数返回或以其他方式阻止这种delete[]情况发生的危险。如果发生这种情况,那么您将丢失指向已分配内存的唯一指针,它将保持已分配但无法访问;这称为内存泄漏。出于这个原因,最好将数组包装在一个类中,其中:

  • 成员变量来存储指向数组的指针,以及(可选)它的大小
  • 分配数组的构造函数和/或函数
  • 用于删除数组的析构函数
  • (可选)调整数组大小的函数

在对象的析构函数中删除分配使用RAII的原理来确保数组一旦不再需要就被删除。

这留下了另一个危险:如果你复制这个数组对象,那么你最终会得到两个对象,它们都试图删除同一个数组,这是灾难性的。为了防止这种情况,您需要考虑三法则。要么编写一个复制构造函数和复制赋值运算符来分配一个新数组并复制内容;或删除它们。(如果你正在学习老式的 C++,那么你不能删除成员函数,所以你必须将它们声明为私有而不是实现它们)。

使用 STL 不是更聪明吗?

通常,是的。但是,如果您正在学习 C++,那么了解内存管理的工作原理以及如何让库为您处理它是一个好主意。这可能是本练习的重点之一。

于 2012-08-22T16:16:31.957 回答
1

这种分配的一种常见方法是自己模拟向量的自动扩展行为。在堆上为您的数据分配一个数组,并跟踪它的长度和您存储在数组中的项目数。

用数据填充数组后,将最大大小扩大一些并分配一个新数组。这使您可以将旧数组中的数据复制到新数组中,然后继续添加项目,直到再次用完空间。

于 2012-08-22T16:02:12.557 回答
0

基本上,如果您需要在不使用 STL 的情况下实现动态数组,则必须明确处理内存分配/释放。

基本上你必须:

  • 在第一次构造或使用数组时使用 malloc 分配空间
  • 跟踪插入/删除的元素
  • 完成分配空间后使用 realloc
  • 销毁数组时释放分配的空间

当然,实现一个像 std::vector 这样好的 STL 容器并不是一件容易的事(最终是一个很好的家庭作业!)。

我可以建议如下:

  • 尽可能避免重新分配。空间完成后,分配更多空间以避免不断调用 realloc(参见 std::vector::reserve)
  • 删除元素时避免重新分配空间。一旦分配完毕,除非内存使用率太高,否则让分配的空间保持原样,以免将来重新分配。
于 2012-08-22T16:10:38.743 回答
0

使用 STL(向量或 C++11 数组)而不依赖文件中的数字会不会更聪明,因为它可能不准确导致缓冲区溢出等?

std::vector 的内部结构并不神奇。可以手动执行 std::vector 为您执行的操作。

听起来这就是你应该为这个任务做的事情;制作自己的“ATM 类型”,可以安全地管理从 ATM.txt 文件中读取数据,以及可以保存来自 accounts.txt 文件的数据的“帐户类型”。您可能应该从编写作业的人那里得到一些澄清,说明他们希望这些类型被设计/使用的准确程度。回顾一下你所拥有的任何课程材料,你应该告诉你在使用动态数组方面你需要知道什么。

于 2012-08-22T16:14:45.687 回答
-1

由于这是家庭作业,我们不想直接给出答案,但总的来说,我的建议是:

  1. 创建一个类 myDynamicArray
  2. 使类包含一个 int 或 long 来存储数组大小
  3. 使用“new”为您的阵列分配内存。从作业来看,它可能是一个字符串数组,或者,如果教授严格禁止 STL(字符串现在被认为是 STL),它将是一个字符数组数组。
  4. 编写一个插入方法,在插入之前检查数组的大小(参见 #2),如果不够大,则将其变大。一种不使用 pre-C++ 函数的方法(我认为这是最好的,因为这是一个 C++ 类)是分配一个更大尺寸的新数组 --> 从旧数组复制数据 --> 插入任何新数据。大多少?例如,您可能会选择每个新分配增加 20%。微软的 C# 分配“下一个最大的素数”元素,尽管它们具有非常快的内存分配例程。
  5. 完成后不要忘记 delete() 动态数组(“完成”的含义取决于分配)。请注意,一旦程序退出,从技术上讲,内存应该会自动释放,但自己不释放它是非常糟糕的做法(想想不定期关闭的大型非学术程序)。

我会避免使用其他用户提供的模板代码。我确信它是很棒的代码,但是使用早期 C++ 类中先进的东西会引起人们的注意。

推荐阅读: http ://www.cplusplus.com/doc/tutorial/dynamic/

于 2012-08-22T16:20:01.067 回答