2010-09-17 97 views
12

我已經編程很糟糕了很長一段時間,我只是真正意識到。我以前創建了許多將字符串作爲char數組返回的函數(或者至少指向它們的指針)。如何返回在函數中創建的字符數組?

有一天有人指出,當我的函數返回由我的函數指向的char數組已經超出範圍,我現在基本上指向一個隨機位的內存(一個討厭的懸掛指針)。

我沒有真正注意到這一段時間,因爲char數組輸出到控制檯時似乎沒有損壞(可能是因爲沒有時間來覆蓋這些數據)。但是,當我返回通過讀取頻繁被破壞的串行端口而生成的字符串緩衝區(char數組)時,我注意到了這一點。

那麼,我該如何做到最好?

我糟糕的代碼如下:

#include <cstdlib> 
#include <iostream> 

using namespace std; 

char* myBadFunction(){ 
    char charArray[] = "Some string\n"; 
    char* charPointer = charArray; 
    return charPointer; 
} 


int main(int argc, char** argv) { 

    cout << myBadFunction(); 

    return 0; 
} 

我知道我應該在程序中調用該函數之前也許分配內存或創建一個全局變量把返回的字符串中,但如果我調用的函數被許多不同的程序使用,它應該如何知道事先傳入緩衝區的大小以及應該何時刪除該內存?

下面的代碼也沒有做什麼,我希望它正確:

#include <cstdlib> 
#include <iostream> 

using namespace std; 

void fillArray(char* charPointer){ 
    char charArray[] = "Some string\n"; // Create string 
    charPointer = charArray; // Not correct, want to fill predefined array with created string 
    return; 
} 


int main(int argc, char** argv) { 

    char predefinedArray[50] = {0}; 
    fillArray(predefinedArray); 
    cout << predefinedArray; 

    return 0; 
} 

我想,以填補該指針解析指向但這並不」在上面的代碼中發生的陣列。

另外,什麼時候應該使用新的[]命令來創建我的數組?需要嗎?什麼時候應該調用它的delete []。

非常感謝這一點,它顯然非常基本,但我一直在做錯了一段時間。

+1

你最好添加你在代碼中寫的代碼。 – Stefanvds 2010-09-17 08:03:03

+0

關於你的問題的第二部分,你將不得不手動循環和複製每個字符到第二個數組或使用'memcpy' ... – st0le 2010-09-17 08:03:50

回答

10

最簡單的方法是返回std::string,如果您需要訪問內部字符數組,請使用std::string::c_str()

#include <iostream> 
#include <string> 

using namespace std; 

string myGoodFunction(){ 
    char charArray[] = "Some string\n"; 
    return string(charArray); 
} 


int main(int argc, char** argv) { 
    cout << myGoodFunction(); 
    return 0; 
} 

如果您需要返回char數組以外的內容,請記住指針可以用作迭代器。這使您可以將數組封裝在向量或類似結構中:

vector<int> returnInts() { 
    int someNums[] = { 1, 2, 3, 4 }; 
    return vector<int>(someNums, someNums + 4); 
} 
+6

我不同意。雖然這解決了當前的問題,但它沒有解釋使用其他類型的數組的問題。我不會低估,這是不公平的,但更好的答案可以解釋他最初的代碼存在的問題。 – 2010-09-17 08:09:53

+0

對於'std :: string',普通的舊C數組是*所以*不是C++ ... – fredoverflow 2010-09-17 08:24:17

+1

@Alexander:好點。我已更新我的回答以反映您的評論。 – Paul 2010-09-17 08:25:08

6

您有兩種選擇以C++返回數組。你可以填寫預先分配好的內存(好的),或者在函數中分配你自己的內存並返回(壞)。第一個是首選的原因是因爲它重新強制正確處理分配的內存。

一個基本的例子是這樣的:

void fillArray(char* buffer, int sz) { 
    char text[] = "hello there!"; 
    if (sizeof(text)>sz) { 
    // overflow! Buffer is too small! 
    return; 
    } 
    for (int n=0;n<sizeof(text);n++) { 
    buffer[n] = text[n]; 
    } 
} 

int main() { 
    char* buffer = new char[30]; // allocates a buffer of 30 bytes. 
    fillArray(buffer,30); 
    cout << buffer; 
    delete [] buffer; 
} 

/* note that it would be easier to use static memory in this example */ 

它當你想到這個問題並不難。

+0

除了何時調用new []和何時刪除[]時,這可以解決問題?另外如果添加的字符串是由cin >> string動態分配的呢?誰應該知道內部函數傳遞給它的緩衝區的大小? – Zac 2010-09-17 08:23:20

+0

您在主函數中分配內存。該函數不需要知道緩衝區大小,除非有可能發生溢出。我會爲你更新我的答案。 – 2010-09-17 10:08:04

1

聲明數組爲「靜態」變量並返回其地址。 此代碼的工作,但會導致一個警告:

#include <cstdlib> 
#include <iostream> 
using namespace std; 

char* myBadFunction(){ 
    static char charArray[] = "Some string\n"; // insert "static" 
    // char* charPointer = charArray; 
    return charArray;    // charArray is a pointer to the static array 
}         // after returning static varibles stay safe 
int main(int argc, char** argv) { 
    cout << myBadFunction(); 
    return 0; 
} 
+0

什麼時候釋放靜態數組所使用的內存?我自己必須這樣做嗎? – 2013-12-09 03:37:44

1

「一些字符串\ n」是一個字符串,因此將存在於程序的生命週期,所以下面將是有效的:

#include <cstdlib> 
#include <iostream> 

using namespace std; 

char* myGoodFunction(){ 
    char* charPointer = "Some string\n"; 
    return charPointer; 
} 

int main(int argc, char** argv) { 
    cout << myGoodFunction(); 

    return 0; 
} 

當然這隻有在函數總是返回相同的字符串時纔有用。如果返回的字符串可能會有所不同(通常是這種情況),那麼您可以將函數中的char數組聲明爲static並返回它的地址(如已經建議的那樣)。