2016-08-04 80 views
1

我有這樣的代碼:不同的輸出取決於刪除

#include <iostream> 
using namespace std; 
char* pass(char* p){ 
    char* a = new char[10]; 
    a[0] = 'S'; 
    a[1] = 'e'; 
    a[2] = 'r'; 
    a[3] = 'g'; 
    a[3] = 'e'; 
    a[3] = 'y'; 
    a[4] = '\0'; 
    p = a; 
    //delete [] a; 
    return p; 
} 
int main(int argc,char* argv[]){ 
    char* p1 = new char[1000]; 
    p1[0] = 'G'; 
    p1[1] = 'e'; 
    p1[2] = 'r'; 
    p1[3] = 'y'; 
    p1[4] = '\0'; 
    char* p2 = p1; 
    cout << p2 << endl; 
    cout << pass(p2) << endl; 
    delete [] p1; 
} 

,輸出是:

Gery 
Sery 

,但如果我取消對該行delete [] a 我得到這樣的輸出:

Gery 
ê§É 

爲什麼?

+2

'p在節目的末尾刪除分配的內存= A;'不復制值,你可能會認爲。 – DimChtz

+3

你應該真的在C++中刷新指針和內存管理。看起來有太多你不明白的答案是有效的。 –

+0

這就是爲什麼你應該使用'std :: stirng'並讓實現擔心分配和複製。 – NathanOliver

回答

2

在此功能

char* pass(char* p){ 
    char* a = new char[10]; 
    a[0] = 'S'; 
    a[1] = 'e'; 
    a[2] = 'r'; 
    a[3] = 'g'; 
    a[3] = 'e'; 
    a[3] = 'y'; 
    a[4] = '\0'; 
    p = a; 
    //delete [] a; 
    return p; 
} 

所述參數是所述函數的一個局部變量。退出該功能後,它將被銷燬。

你能想象的功能和它的調用方式如下

pass(p2); 

char* pass(/*char* p*/){ 
    char* p = p2; 
    char* a = new char[10]; 
    a[0] = 'S'; 
    a[1] = 'e'; 
    a[2] = 'r'; 
    a[3] = 'g'; 
    a[3] = 'e'; 
    a[3] = 'y'; 
    a[4] = '\0'; 
    p = a; 
    //delete [] a; 
    return p; 
} 

正如你看到原來的指針p2不會在功能被改變。該函數更改其聲明爲參數的本地變量p

如果取消註釋刪除語句,則返回值指向的內存將被刪除,並且返回的指針將無效。在這種情況下,程序是未定義行爲由於聲明

cout << pass(p2) << endl; 

那裏是使用函數的返回值來訪問內存中刪除的嘗試。

所以沒有意義將指針返回到已刪除的內存。

你想做的事可以通過三種方式

第一個是聲明參數作爲參考

char* pass(char* &p){ 
      ^^^^^^^^ 
    char* a = new char[10]; 
    a[0] = 'S'; 
    a[1] = 'e'; 
    a[2] = 'r'; 
    a[3] = 'g'; 
    a[3] = 'e'; 
    a[3] = 'y'; 
    a[4] = '\0'; 
    p = a; 
    return p; 
} 

和調用函數一樣

cout << pass(p2) << endl; 

第二個實現什麼一種是將參數聲明爲指向間接接受原始指針的指針

char* pass(char* *p){ 
      ^^^^^^^^ 
    char* a = new char[10]; 
    a[0] = 'S'; 
    a[1] = 'e'; 
    a[2] = 'r'; 
    a[3] = 'g'; 
    a[3] = 'e'; 
    a[3] = 'y'; 
    a[4] = '\0'; 
    *p = a; 
    ^^^^^^^^ 
    return *p; 
    ^^^^^^^^^^ 
} 

,並呼籲像

cout << pass(&p2) << endl; 

功能,最後你可以返回值只是將原來的指針。例如

char* pass(char* p){ 
    char* a = new char[10]; 
    a[0] = 'S'; 
    a[1] = 'e'; 
    a[2] = 'r'; 
    a[3] = 'g'; 
    a[3] = 'e'; 
    a[3] = 'y'; 
    a[4] = '\0'; 
    p = a; 
    return p; 
} 

,並呼籲像

cout << (p2 = pass(p2)) << endl; 

的functionj儘管在這種情況下,參數是過時的。

在任何情況下,你應該像

delete [] p2; 
1
p = a 

不復制值。

你所尋找的可能是:

memcpy(p, a, 10*sizeof(char)); 
+2

我不認爲這是一個有用的答案:首先,它不是C++的做事方式。並沒有真正解釋發生了什麼。最後,即使在低級別的C++環境下,你也不會編寫這樣的代碼(使用'std :: copy'代替,或者至少包含正確的頭文件並刪除無用的'sizeof(char)')。 –

+0

@KonradRudolph I agrre因爲在任何情況下返回的指針都會指向刪除內存,如果取消註釋刪除語句.. –

0

因爲你註釋掉線來釋放你返回的內存,和你的編譯器,可能協助調試,改寫釋放內存。

您的p是通過值,所以p = a;不,實際上,在主內部改變p1。你基本上初始化內存,刪除它,然後返回一個指向已刪除內存的指針。

沒有額外的刪除,你只是泄漏該內存。