解释此C++函数如何返回数组
Explain how this C++ function returns an array
我在网上找到了这段代码 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;
}
I.
int *ret=new int[s];
1. 为堆栈上的ret
分配内存 - 这是一个int
指针
2. 在堆
上分配大小为 s * sizeof(int)
的连续内存3. 使ret
指向已分配内存的第一个元素(从 2.(
第二。
for (size_t a=0;a<s;a++)
ret[a]=a;
- 在
- 堆栈上分配内存以供
a
- 循环遍历 I 中分配的内存,为每个元素赋值
for
-语句结束后,a
不再可访问(仅在for
中可用(
第三。
return ret;
返回 ret
指针的副本,该指针指向在 I 中创建的第一个元素。 数组,在 II 中初始化。
return
后,ret
被"摧毁"。
此
函数的调用者一定不要忘记释放(释放(此内存,调用delete[]
。
例如:
int * my_array = f( 6 );
// do sth with my_array
delete[] my_array;
实际上,该函数不会返回 int
s 的数组(即 int[N]
(。它返回的是指向int
(int *
(的指针。事实证明,此指针指向类型为 int
的 s
元素数组的第一个元素。
请注意,内存分配有new
:
int *ret = new int[s];
因此,ret
指向的int
数组具有动态存储持续时间。除其他事项外,这意味着
1( 编译器不会自动调用每个数组元素的析构函数。(在这种情况下,这不是问题,因为元素的类型是 int
但可能是 elemets 的,其中具有非平凡析构函数的类类型。
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
确实抛出异常,则执行永远不会达到删除p
的点。在这种情况下,内存按new
分配(f
内部(不会释放(泄漏(,直到程序终止。
为了避免这个问题,而不是原始指针(例如 int*
(最好使用智能指针(例如 std::unique_ptr
或std::shared_ptr
(。
最后,默认情况下,new
分配的内存是堆内存。然而您可以更改此行为。
int *ret=new int[s];
此行定义了一个名为 ret
的具有自动存储持续时间的int*
。它使用新表达式返回的指针初始化ret
new int[s]
。此新表达式创建一个具有动态存储持续时间的 s
int
数组,并返回指向该数组中第一个元素的指针。
所以我们现在有两个对象:一个具有自动存储持续时间的int*
和一个具有动态存储持续时间的int[]
。
for (size_t a=0;a<s;a++)
这是一个for
的说法。for-init-语句定义了一个名为 a
的size_t
对象,并将其初始化为 0。该条件检查a
是否小于 s
。最后一个表达式递增a
。这意味着a
循环的范围[0, s)
.
ret[a]=a;
这会将 a
的值分配给 ret
中的第 a
个元素。也就是说ret[0]
将具有值 0
,ret[1]
将具有值 1
,依此类推。
a
对象现在已被销毁,因为它具有自动存储持续时间,并且我们已经到达其范围的末尾(for
语句(。
return ret;
这将返回 ret
的值,您还记得这是一个int*
。因此,函数的返回值是一个指向动态分配数组的第一个元素的int*
。
ret
对象现在被销毁,因为它具有自动存储持续时间,并且我们已经到达了其作用域(f
函数(的尽头。请注意,这只是函数内的指针。动态分配的数组仍然存在,返回的指针仍指向它。
在以后的某个时间点,您必须记住delete[]
返回的指针。
int *ret = new int[s];
这会动态地(在堆上~(分配一个s
整数数组,并在ret
中存储指向它的指针(实际上是指向其第一个元素(。
我相信函数的其余部分很简单。
因此,该函数将返回指向动态分配数组的指针。这不是很安全;如果调用方不存储返回值,稍后对其调用delete[]
,它将泄漏。
- 从 C++ 中的函数返回数组地址问题
- 如何在 c++ 函数中返回数组
- 如何从 c++ 中的函数返回数组
- 为什么 c++ 函数可以正确返回数组的大小?
- 解释通过从函数引用返回数组的语法
- (C++)我的函数不返回数组
- 如何按 C++ 中的值从函数返回数组
- 返回数组中值的指针地址
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 使用数组类返回数组c++
- 如何使函数返回数组?用于制作在VB.NET中使用的DLL
- 从函数 BY VALUE 返回数组,返回结构时会发生什么?
- 调用和打印函数,在 C++ 中返回数组
- 如何使用递归函数返回数组中整数的索引?
- 从函数返回数组时是否需要删除
- 为什么从函数返回数组时需要将数组声明为静态数组.(C++)
- C++返回数组而不进行动态内存分配?
- 在函数 c++ 中返回数组时出现问题
- 如何从C 中的函数返回数组
- 如何使类函数返回数组,然后将其调用并存储在 main 中