2012-07-02 18 views
1

在下面的代碼中,我嘗試使用C++構建2D數組,但是當我運行此程序時,它失敗。爲什麼要以這種方式刪除二維數組失敗(C++)?

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

int obtain_options( char ** optionLine) 
{ 
    vector< char*> options; 
    options.push_back("abc"); 
    options.push_back("def"); 


    std::copy(options.begin(), options.end(), const_cast< char**>(optionLine)); 

    return options.size(); 
} 

int main(int ac, char* av[]) 
{ 
    char** optionLine; 
    int len; 
    optionLine = new char* [2]; 
    for (int i= 0; i<2; i++) 
    { 
     optionLine[i] = new char [200]; 
    } 
    obtain_options(optionLine); 
    for (int i=0; i<2; i++) 
    { 
     cout<<optionLine[i]<<endl; 
    } 

    for (int i=0; i<2; i++) 
     delete [] (optionLine[i]); 
    delete []optionLine; 

    return 0; 

} 

我知道有一些問題,在功能obtain_options()分配內存optionLine,如果我改變obtain_options()這樣一來,它的工作:

int obtain_options( char ** optionLine) 
{ 
    vector< char*> options; 
    char *t1 = new char [100]; 
    t1[0] = 'a'; 
    t1[1] = 'b'; 
    t1[2] = 'c'; 
    t1[3] = '/0'; 
    options.push_back(t1); 
    char *t2 = new char [100]; 
    t2[0] = 'd'; 
    t2[1] = 'e'; 
    t2[2] = 'f'; 
    t2[3] = '/0'; 
    options.push_back(t2); 


    std::copy(options.begin(), options.end(), const_cast< char**>(optionLine)); 

    return options.size(); 
} 

我的問題是,如果我不改變obtain_options(),我怎麼能以適當的方式刪除二維數組optionLine。

+0

對不起,也許我錯過了一些東西。你在哪裏調用obtain_options? – yuklai

+0

正在使用'obtain_options'在哪裏? – Alex

+0

你的目標是什麼?我最好的建議是簡單地拋棄所有'char *'和'new',並使用'std :: string'。一切都應該「只是工作」。 – Chad

回答

2

你的向量包含一組字符指針。但是,這些字符串指向的實際內存並不像您期望的那樣連續。所以,這個電話不會像你期望的那樣工作。

std::copy(options.begin(), options.end(), const_cast< char**>(optionLine)); 

在最壞的情況下,你可以做到這樣的,這就是你幾乎做自己吧。

for (int i= 0; i<2; i++) 
{ 
    strcpy(optionLine[i],options[i]); 
} 

但是要避免所有這些內存處理,除非你正在學習指針和分配。

瞭解如何整齊,你可以像在C++代碼這一點:自己

int obtain_options(vector<string>& anOptions_out) 
{ 
    anOptions_out.push_back("abc"); 
    anOptions_out.push_back("def"); 

    return anOptions_out.size(); 
} 

int main(int ac, char* av[]) 
{ 
    vector<string> anOptions; 
    obtain_options(anOptions); 
    for (int i=0; i<anOptions.size(); i++) 
    { 
     cout<< anOptions[i].c_str() <<endl; 
    } 

    return 0; 
} 

不分配/釋放操作。

1

您發佈的代碼不會調用 obtain_options。但是,我注意到在該函數中,您將字符指針從本地對象( options)複製到 optionLine參數指向的數組。這將是一個問題,因爲從 obtain_options返回後,這些指針將無效。

正如其他人所指出的,以上是對該問題的誤診。

我現在打電話obtain_options後您的代碼做這樣看:

for (int i=0; i<2; i++) 
    delete [] (optionLine[i]); 

這意味着它呼籲指向​​和"def"靜態指針delete操作。

「政治正確」之外,我覺得我原來的建議仍然有效:

嘗試用std::string更換char*,並與vector<std::string>更換char**

+0

返回這些指針沒有問題,因爲它們指向靜態數據。 – lvella

+0

@lvella:但是*有*刪除它們的問題,這是返回後發生的問題。 –

+0

@MikeSeymour是的,這正是OP的問題:如何正確刪除'optionLine'。 – lvella

1

由於大多數人在這裏來講在提供政治上正確解決您發現的問題,而不是回答問題,這裏是我的貢獻:

你是不是複製串到你的手工分配向量的內容,相反,您要更換內部vector< char*> options;

你的指針分配的指針,當你這樣做:

char *a = "abc"; 

而技術上更正確的使用const char,它說a將持有指向靜態分配的C字符串​​(即不變)。當你這樣做:

options.push_back("abc"); 

你把這個指針vector裏面,當你這樣做:

std::copy(options.begin(), options.end(), const_cast< char**>(optionLine)); 

你只需用指針代替原來的三分球optionsLineoptions。與Dan Breslau所說的相反,從函數返回這些指針是沒有問題的,因爲它們是靜態的,即在整個程序期間將存在。雖然使用原始obatin_options功能,您可以簡單地這樣做,因爲你的主:

int main(int ac, char* av[]) 
{ 
    char** optionLine; 
    int len; 
    optionLine = new char* [2]; 
    obtain_options(optionLine) 
    for (int i=0; i<2; i++) 
    { 
     cout<<optionLine[i]<<endl; 
    } 

    delete []optionLine; 

    return 0; 
} 

請注意,我沒有分配optionLine的內容,因爲這將是賠了進去obtain_options(),也obtain_options()是一個非常不安全的功能,因爲沒有辦法確保內容符合提供的數組。將另一個參數size與所提供的optionLine數組的大小相比更安全,然後您不得複製超出其極限。

int obtain_options( char ** optionLine, int size) 
{ 
    vector< char*> options; 
    options.push_back("abc"); 
    options.push_back("def"); 

    if(size > options.size()) 
     size = options.size(); 
    std::copy(options.begin(), options.begin() + size, const_cast< char**>(optionLine)); 

    return size; 
} 

或者,您應該使用PermanentGuest提供的非常安全的解決方案。

+0

謝謝,這正是問題的答案。 – feelfree

+0

@feelfree如果答案滿足您,您應該將其標記爲已接受。該標記低於「投票」/「向下投票」箭頭。 – lvella

相關問題