[英]How can an declare an array in a function that returns an array in 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;
}
一世。
int *ret=new int[s];
1.為堆棧上的ret
分配內存-這是一個int
指針
2.在堆上分配大小為s * sizeof(int)
連續內存
3.使ret
指向已分配內存的第一個元素(從2開始)。
II。
for (size_t a=0;a<s;a++)
ret[a]=a;
a
for
語句結束后, a
將不再可訪問(僅在for
可用) III。
return ret;
返回ret
指針的副本,該副本指向 I.數組中創建的,在II中初始化的第一個元素。
return
, ret
被“銷毀”。
該函數的調用者一定不要忘記通過調用delete[]
來釋放(釋放)該內存。
例如:
int * my_array = f( 6 );
// do sth with my_array
delete[] my_array;
實際上,該函數不會返回int
的數組(即int[N]
)。 它返回的是一個指向int
( int *
)的指針。 事實證明,此指針指向int
類型的s
元素數組的s
元素。
注意,內存分配有new
:
int *ret = new int[s];
因此, ret
指向的int
數組具有動態存儲持續時間。 除其他外,這意味着
1)編譯器不會自動調用每個數組元素的析構函數。 (在這種情況下,這不是問題,因為元素的類型為int
但是如果元素類型為帶有非平凡析構函數的elemets where,則可能是這種情況。)
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
里面)分配的內存才會被釋放(泄漏)。
為避免此問題,最好使用智能指針(例如std::unique_ptr
或std::shared_ptr
)代替原始指針(例如int*
)。
最后,默認情況下,由new
分配的內存是堆內存。 但是,您可以更改此行為。
數組和指針有很多相似之處。 您可以擁有一個指向數組第一個元素的指針,並將其傳遞(或返回)到所需的位置。
int *f(size_t s) // It will return a pointer (maybe first element of an array)
{
int *ret=new int[s]; // Allocates memory in heap,
// An array with s integral elements,
// And stores the address of the array in ret
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret; // Returns the pointer which points first element of the array
}
// ...
int *z = f(10); // z points to the first element of returned array
// ... then you're responsible to free the allocated memory ...
// delete [] z;
int *ret=new int[s];
該行定義一個具有自動存儲持續時間的稱為ret
的int*
。 它使用new-expression new int[s]
返回的指針初始化ret
。 這個new表達式創建一個具有動態存儲持續時間的s
int
數組,返回一個指向該數組中第一個元素的指針。
因此,我們現在有兩個對象:具有自動存儲持續時間的int*
和具有動態存儲持續時間的int[]
。
for (size_t a=0;a<s;a++)
這是一個for
語句。 for-init-statement定義了一個名為a
的size_t
對象,並將其初始化為0。該條件檢查a
是否小於s
。 最終表達式使 a
遞增。 這意味着a
在[0, s)
范圍內循環。
ret[a]=a;
此分配值a
到a
在th元素ret
。 即ret[0]
的值為0
, ret[1]
的值為1
,依此類推。
在a
對象被銷毀,現在因為它有自動存儲時間,我們已經達到其范圍的一端( for
語句)。
return ret;
這將返回ret
的值,您記得它是一個int*
。 因此,該函數的返回值是一個int*
指向動態分配的數組的第一個元素。
ret
對象現在已銷毀,因為它具有自動存儲時間,並且我們已經達到其作用域的末尾( f
函數)。 請注意,這只是函數內部的指針。 動態分配的數組仍然存在,並且返回的指針仍指向該數組。
稍后,您必須記住記住將返回的指針delete[]
。
int *ret = new int[s];
這個動態地(在堆上)分配一個s
整數數組,並在ret
存儲一個指向它的指針(實際上是指向它的第一個元素)。
我相信其余功能很簡單。
因此,該函數將指針移回動態分配的數組。 這不是很安全; 如果調用方不存儲返回值,而后又在其上調用delete[]
,則它將泄漏。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.