2012-06-27 114 views
0

我有一個字符串向量,它沒有明顯的原因正在改變它的內容。無法真正解釋發生了什麼事。對不起,很長的列表,但它真的讓我煩惱。std :: vector的消失內容<std::string>

我有一個GUI應用程序,加載一些文件,並使用一個閱讀器對象,可以使用parse(int argc, char* argv[])方法設置狀態。參數在對話框中通過選中各個框並輸入值來設置。這裏是一個結構我用從該對話框中保存數據:

struct PointFilter 
{ 
    PointFilter(): argc(0) {}; 
    ~PointFilter() {}; 
    int argc; 
    std::vector<std::string> args; 
}; 

這個結構是對話框類的成員,然後按確定按鈕其填入適當的值之後。值從文本框採取的對話框上成字符串流,然後推回一個std ::向量:

class AdvancedLoadDialog 
{ 
public: 
    AdvancedLoadDialog(const Glib::RefPtr<Gtk::Builder>&); 
    ~AdvancedLoadDialog(); 

    PointFilter get_point_filter() 
    { 
     return this->point_filter; 
    } 

private: 
    PointFilter point_filter; 
    void on_ok_btn_clicked(); 

void AdvancedLoadDialog::on_ok_btn_clicked() 
{ 
    std::stringstream filter_stream; 
     // filter_stream << some_values_from_textboxes ... 

    std::vector<std::string> args; 
    std::string arg; 

    // we need a dummy first argument to emulate the command line 
    args.push_back("filter"); 

    while (filter_stream >> arg) 
    { 
     args.push_back(arg); 
    }  

    point_filter.argc = args.size() > 1 ? args.size() : 0; 
    point_filter.args = args; 

    advanced_load_dialog->hide_all(); 
} 

一切正常,直到這一點上,我們必須適應point_filter成員的AdvancedLoadDialog對象持有我們的論據。現在在一個單獨的窗口中,我使用point_filter對象並將其傳遞給LoadWorker類的構造函數,該類將加載文件,並且還有一個PointFilter成員。

load_worker = new LoadWorker(..., advanced_load_dialog->get_point_filter()) 

然後:

LoadWorker::LoadWorker(..., PointFilter pf) : 
    point_filter (pf) 

一切都很好。現在在LoadWorker::run()函數中,我從point_filter獲取參數,將它們轉換爲std :: vector並將它們傳遞給我需要的parse(int argc,char * argv [])函數。

void LoadWorker::run() 
{ 
    std::cout << "LoadWorker::file_filter contents: \n" 
      << "point_filter.argc: " << point_filter.argc << "\n" 
      << "point_filter.args: " << std::endl; 
    for (int i = 0; i < point_filter.argc; ++i) 
     std::cout << point_filter.args[i] << std::endl; 

     // ... 

    if (point_filter.argc != 0) 
    { 
     std::cout << "Using filter: " << std::endl; 

     std::vector<char*> argv; 

     for (std::vector<std::string>::const_iterator it = point_filter.args.begin(); 
       it != point_filter.args.end(); ++it) 
     { 
      argv.push_back(const_cast<char*>(it->c_str())); 
     } 
     argv.push_back(0); 

     for (int i = 0; i < point_filter.argc; ++i) 
     { 
      std::cout << argv[i] << std::endl; 
     } 

     if (!lasreadopener.parse(point_filter.argc, &argv[0])) 
     { 
      send_message("Error parsing filter parameters."); 
      sig_fail(); 
      return; 
     } 
    } 
} 

現在這項工作...一次。您可以注意到參數會被打印兩次,首先作爲LoadWorker::point_filter.args向量的元素,然後作爲vector<char*> argv的元素。如果我設置過濾器,然後按下加載按鈕,它一切正常。如果我然後嘗試加載另一個文件,而根本不改變AdvancedLoadDialog::point_filter,則參數正在消失。這裏有一個示例輸出,試圖在一行中加載兩個文件。

LoadWorker :: FILE_FILTER內容:point_filter.argc:6個 point_filter.args:濾波器 -clip_z_above 12 -keep_intensity 11 222使用濾波器:濾波器 -clip_z_above 12 -keep_intensity 11 222 LoadWorker :: FILE_FILTER內容:point_filter.argc:6個point_filter.args:濾波器clip_z_above 2 keep_intensity 1 22使用濾波器:濾波器

// 6空白行這裏

爲了使它更奇怪,在第二次運行期間,除point_filter.args中的第一個字符串以外的每個字符串都缺少第一個字符,而在argv中它們全部爲空。

任何線索?

+2

'parse'修改'char *'是否通過了? – Naveen

+0

我不這麼認爲。會檢查。每次按下加載按鈕時,仍然會刪除並重新創建LoadWorker對象。因此,point_filter的內容是從'AdvancedLoadDialog :: point_filter'重新創建的,它根本不應該改變。 – jaho

+1

const_cast (it-> c_str())永遠不要這樣做! http://stackoverflow.com/questions/347949/convert-stdstring-to-const-char-or-char –

回答

1

要非常,涉及std::string::c_str做事非常謹慎,你在這裏做:

argv.push_back(const_cast<char*>(it->c_str())); 

如果你想保留通過c_str提供的值,你應該首先將它們複製到一個新的容器。

如果cplusplus.com是被信任的(這並不總是如此),

此數組中的值不應在程序進行修改,並且只保證保持不變,直到到下一個呼叫字符串對象的非常量成員函數

儘管我不能立即將其他來源的任何其他有用信息放在手邊。

+0

我知道。它返回一個指向std :: string佔用的內存位置的指針,所以如果這改變了,我可能會遇到麻煩。然而,'point_filter.args'是構造函數中創建的'LoadWorker'的成員,所以只要對象存在就不應該改變。此外,爲什麼'point_filter.args'中的字符串缺少第一個字符。我假設c_str()不能造成這種情況。 – jaho

1

在AdvancedLoadDialog中,嘗試推送分配的arg版本而不是自動版本。您似乎在推送一個將在離開AdvancedDialogLoad時將被破壞的變量的引用。

相關問題