2

为某些数据分配内存有什么好处。相反,我们可以使用它们的数组。

喜欢

 int *lis;
 lis = (int*) malloc ( sizeof( int ) * n );

 /* Initialize LIS values for all indexes */
 for ( i = 0; i < n; i++ )
 lis[i] = 1;

我们可以使用一个普通的数组。

好吧,我不明白 malloc 是如何工作的,实际上是什么。所以解释它们对我来说会更有益。

假设我们sizeof(int) * n只替换n上面的代码,然后尝试存储整数值,我可能会遇到什么问题?有没有办法直接从内存分配的空间打印存储在变量中的值,例如这里是lis

4

6 回答 6

6

您的问题似乎是将动态分配的 C 样式数组与可变长度数组进行比较,这意味着这可能就是您要寻找的内容:为什么可变长度数组不是 C++ 标准的一部分?

然而,标签产生了最终的答案:使用std::vectorobject 代替。

只要可能,避免动态分配和丑陋的内存管理责任〜>尝试利用具有自动存储持续时间的对象。另一个有趣的阅读可能是:理解术语和概念的含义 - RAII(资源获取即初始化)


“假设我们sizeof(int) * n只替换n上面的代码,然后尝试存储整数值,我可能会遇到什么问题?”
- 如果您仍然认为n是可以存储在此数组中的整数数量,您很可能会遇到未定义的行为

于 2013-09-09T16:19:56.710 回答
3

更根本的是,我认为,除了堆栈与堆以及变量与常量的问题(以及你不应该malloc()在 C++ 中使用的事实之外),当函数退出时,本地数组不再存在。如果你返回一个指向它的指针,那么一旦调用者接收到它,该指针就会变得无用,而动态分配的内存malloc()new仍然有效。例如,您无法实现像strdup()使用本地数组这样的功能,也无法明智地实现链接表示列表或树。

于 2013-09-09T16:32:17.807 回答
2

答案很简单。本地1数组分配在您的堆栈上,这是为您的程序预先分配的一小块内存。除了几千个数据,你真的不能在堆栈上做很多事情。对于更多的数据,您需要从堆栈中分配内存。

这就是这样malloc做的。

malloc分配一块与您要求一样大的内存。它返回一个指向该内存开头的指针,可以将其视为类似于数组。如果您写入超出该内存的大小,则结果是未定义的行为。这意味着一切都可以正常工作,否则您的计算机可能会爆炸。尽管您很可能会遇到分段错误错误。

从内存中读取值(例如用于打印)与从数组中读取相同。例如printf("%d", list[5]);.

在 C99 之前(我知道这个问题被标记为 C++,但可能你正在学习 C-compiled-in-C++),还有另一个原因。你不可能在堆栈上有一个可变长度的数组。(即使现在,堆栈上的可变长度数组也不是很有用,因为堆栈很小)。这就是为什么对于可变数量的内存,您需要该malloc函数根据需要分配内存,其大小在运行时确定。

局部数组或任何局部变量之间的另一个重要区别是对象的生命周期。局部变量的作用域一结束就无法访问。malloced 对象一直存在,直到它们成为freed。这在几乎所有不是数组的数据结构中都是必不可少的,例如链表、二叉搜索树(和变体)、(大多数)堆等。

malloced 对象的一个​​例子是FILEs。一旦调用fopen,保存与打开文件相关的数据的结构将使用malloc指针 ( FILE *) 动态分配并返回。


1注意:非局部数组(全局或静态)在执行之前分配,因此它们实际上无法在运行时确定长度。

于 2013-09-09T16:20:30.467 回答
1

我假设您在问 c 的目的是什么maloc():假设您想从用户那里获取输入,现在分配一个该大小的数组:

int n;
scanf("%d",&n);
int arr[n];

这将失败,因为 n 在编译时不可用。来了malloc() 你可以写:

int n;
scanf("%d",&n);
int* arr = malloc(sizeof(int)*n);

实际上malloc()是在堆区动态分配内存

于 2013-09-09T16:24:54.783 回答
0

一些较旧的编程环境根本没有提供malloc或任何等效功能。如果您需要动态内存分配,您必须自己在巨大的静态数组之上编写代码。这有几个缺点:

  • 静态数组大小对程序可以在任何时候处理的数据量设置了一个硬性上限,而无需重新编译。如果您曾经尝试在 TeX 中做一些复杂的事情并收到“超出容量,抱歉”消息,这就是原因。
  • 操作系统(例如它)必须一次性为静态数组保留空间,无论是否全部使用。这种现象导致了“过度使用”,在这种情况下,操作系统假装已经分配了您可能需要的所有内存,但如果您实际尝试使用的内存超出可用内存,则会终止您的进程。为什么会有人想要那个?然而,它在 90 年代中期的商业 Unix 中被大肆宣传为一项功能,因为这意味着可能需要比您的小型 Sun 工作站更多的内存的巨型 FORTRAN 模拟可以在小型实例上毫无问题地进行测试。(大概你会在 Cray 上运行一个大实例,它实际上有足够的内存来处理。)
  • 动态内存分配器很难很好地实现。看看jemalloc 纸,了解它有多毛。(如果您想要自动垃圾收集,它会变得更加复杂。)这正是您希望大师为每个人的利益编写一次代码的那种事情。

因此,如今即使是非常准系统的嵌入式环境也可以为您提供某种动态分配器。

但是,尝试不这样做是很好的心理纪律。动态内存的过度使用会导致效率低下,这种情况通常很难在事后消除,因为它已融入架构中。如果手头的任务似乎不需要动态分配,也许它不需要。

然而,当你真正应该使用动态内存分配时,使用动态内存分配可能会导致其自身的问题,例如对字符串的长度施加硬性上限,或者在你的 API 中加入不可重入性(比较gethostbynamegetaddrinfo

所以你必须仔细考虑。

于 2013-09-09T16:35:15.397 回答
0

我们可以使用一个普通的数组

在 C++ 中(至少今年是这样),数组具有静态大小;所以从运行时值创建一个:

int lis[n];

不被允许。一些编译器允许将其作为非标准扩展,明年将成为标准;但是,现在,如果我们想要一个动态大小的数组,我们必须动态分配它。

在 C 语言中,这意味着搞乱malloc; 但你问的是 C++,所以你想要

std::vector<int> lis(n, 1);

分配一个大小数组,n其中包含int初始化为 1 的值。

(如果你愿意,你可以用 分配数组new int[n],并记得delete [] lis在完成后释放它,如果抛出异常,请特别注意不要泄漏;但生命太短暂了,不适合这种废话。)

好吧,我不明白 malloc 是如何工作的,实际上是什么。所以解释它们对我来说会更有益。

malloc在 C 和newC++ 中,从“免费存储”中分配持久内存。与局部变量的内存不同,当变量超出范围时会自动释放,这会一直存在,直到您显式释放它(free在 C 中,delete在 C++ 中)。如果您需要数组比当前函数调用更有效,这是必要的。如果数组非常大,这也是一个好主意:局部变量(通常)存储在堆栈上,大小有限。如果溢出,程序将崩溃或出错。(并且,在当前的标准 C++ 中,如果大小不是编译时常量,则它是必要的)。

假设我们sizeof(int) * n只替换n上面的代码,然后尝试存储整数值,我可能会遇到什么问题?

您没有为n整数分配足够的空间;因此假设您拥有的代码将尝试访问超出分配空间末尾的内存。这将导致未定义的行为;运气好的话会崩溃,运气不好的话会损坏数据。

有没有办法直接从内存分配的空间打印存储在变量中的值,例如这里是lis

你的意思是这样的?

for (i = 0; i < len; ++i) std::cout << lis[i] << '\n';
于 2013-09-09T16:36:11.040 回答