0

我在网上找到了这段代码http://www.cplusplus.com/forum/beginner/6644/#msg30551它应该从 c++ 函数返回一个数组。我想要一个解释说明这个函数如何在内存分配、堆栈、堆、指针等方面运行。

int *f(size_t s){
    int *ret=new int[s];
    for (size_t a=0;a<s;a++)
        ret[a]=a;
    return ret;
}
4

4 回答 4

3

我。

int *ret=new int[s];

1.ret在堆栈上分配内存 - 这是一个int指针2.在堆上
分配具有大小的连续内存 3.指向已分配内存的第一个元素(来自 2.)s * sizeof(int)
ret


二、

for (size_t a=0;a<s;a++)
    ret[a]=a;
  1. 在堆栈上分配内存a
  2. 循环遍历 I. 中分配的内存,为每个元素赋值
  3. for-statement结束后,a不再可访问(仅在 中可用for

三、

return ret;

返回指针的副本ret,它指向在 I. 中创建的数组的第一个元素,在 II 中初始化。

之后returnret被“销毁”。


这个函数的调用者不能忘记释放(释放)这个内存,调用delete[].

例如:

int * my_array = f( 6 );
// do sth with my_array
delete[] my_array;
于 2013-03-21T10:23:19.757 回答
1

实际上,该函数不返回ints 数组(即int[N])。它返回的是一个指向int( int *) 的指针。s事实证明,这个指针指向类型元素数组的第一个元素int

请注意,内存分配有new

int *ret = new int[s];

int因此,所指向的s数组ret具有动态存储时长。除其他外,这意味着

1) 编译器不会自动调用每个数组元素的析构函数。(在这种情况下,这不是问题,因为元素是类型的,int但如果元素是具有非平凡析构函数的类类型的元素,则可能是。)

2) 编译器不会自动释放分配的内存。

相比之下,请考虑以下代码:

void g() {
    int p[10]; // allocates 10 integer in the stack
    // use p ...
}

g终止时,编译器将执行上述操作。为此,必须在编译时设置数组的大小(本例中为 10)。如果您在编译时不知道大小,而不是new原始代码中所需的大小。

对于动态分配的数组,程序员有责任确保在不再需要数组时执行上述两个操作。为此,您必须调用delete[]

delete[] p; // where p is a `int*` with the same value as `ret`

实际上,由于可能引发异常,这比看起来要困难得多。例如,考虑这段代码

void foo() {
    int* p = f(10); // where f is in the question
    // ... use the array pointed by p
    a_function_that_might_throw();
    delete[] p;
}

如果确实抛出异常,则执行永远不会到达被删除a_function_that_might_throw的地步。在这种情况下,由(inside )p分配的内存在程序终止之前不会被释放(它会泄漏)。newf

int*为了避免这个问题,最好使用智能指针(例如std::unique_ptror )而不是原始指针(例如std::shared_ptr)。

最后,默认情况下,分配的内存new是堆内存。但是,您可以更改此行为。

于 2013-03-21T11:25:14.623 回答
0
int *ret =  new int[s];

这动态地(在堆上)分配一个s整数数组并将一个指向它的指针(实际上,指向它的第一个元素)存储在ret.

我相信其余的功能很简单。

所以该函数将一个指针返回给一个动态分配的数组。这并不安全。如果调用者不存储返回值并稍后调用delete[]它,它将泄漏。

于 2013-03-21T10:24:58.403 回答
0
int *ret=new int[s];

此行定义了一个具有自动存储持续时间的int*调用。它使用new-expression返回的指针进行ret初始化。这个new 表达式创建一个具有动态存储持续时间的 s 数组,返回一个指向该数组中第一个元素的指针。ret new int[s]s int

所以我们现在有两个对象:一个int*具有自动存储持续时间的对象和一个int[]具有动态存储持续时间的对象。

for (size_t a=0;a<s;a++)

这是一个for声明。for-init-statement定义了一个名为的size_t对象a并将其初始化为 0。条件检查是否a小于s。最终表达式递增a。这意味着a在范围内循环[0, s)

ret[a]=a;

这会将 的值分配给 中aa第 th 个元素ret。那就是ret[0]会有价值0ret[1]会有价值1,等等。

a对象现在被销毁,因为它具有自动存储持续时间,并且我们已经到达其范围(for语句)的末尾。

return ret;

这将返回 的值ret,正如您所记得的那样,它是一个int*。因此,函数的返回值int*指向动态分配数组的第一个元素。

ret对象现在被销毁,因为它具有自动存储持续时间,并且我们已经到达其范围(f函数)的末尾。请注意,这只是函数内部的指针。动态分配的数组仍然存在,返回的指针仍然指向它。

稍后,您必须记住delete[]返回的指针。

于 2013-03-21T10:23:45.597 回答