簡體   English   中英

說明此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;
  1. 棧上分配內存a
  2. 遍歷I.中分配的內存,為每個元素分配值
  3. for語句結束后, a將不再可訪問(僅在for可用)

III。

return ret;

返回ret指針的副本,該副本指向 I.數組中創建的,在II中初始化的第一個元素。

returnret被“銷毀”。


該函數的調用者一定不要忘記通過調用delete[]來釋放(釋放)該內存。

例如:

int * my_array = f( 6 );
// do sth with my_array
delete[] my_array;

實際上,該函數不會返回int的數組(即int[N] )。 它返回的是一個指向intint * )的指針。 事實證明,此指針指向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_ptrstd::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];

該行定義一個具有自動存儲持續時間的稱為retint* 它使用new-expression new int[s]返回的指針初始化ret 這個new表達式創建一個具有動態存儲持續時間的s int數組,返回一個指向該數組中第一個元素的指針。

因此,我們現在有兩個對象:具有自動存儲持續時間的int*和具有動態存儲持續時間的int[]

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

這是一個for語句。 for-init-statement定義了一個名為asize_t對象,並將其初始化為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[]

int *ret =  new int[s];

這個動態地(在堆上)分配一個s整數數組,並在ret存儲一個指向它的指針(實際上是指向它的第一個元素)。

我相信其余功能很簡單。

因此,該函數將指針移回動態分配的數組。 這不是很安全; 如果調用方不存儲返回值,而后又在其上調用delete[] ,則它將泄漏。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM