2016-09-01 88 views
1

將字符串值放入「字符串向量結構」中有問題。 最簡單的可重複的代碼如下:C++將字符串放入字符串向量結構

#include <vector> 
#include <string> 
#include <iostream> 

using namespace std; 

struct ttt { 
    string name; 
    unsigned int ID; 
    vector<unsigned int> numList; 
}; 

int main() { 
    vector<ttt> b; 
    b.reserve(3); 
    b[0].ID = 1; 
    b[0].numList.push_back(3); 
    b[0].numList.push_back(4); 
    string dd ("Desk"); 
    b[0].name = dd; 
    cout << b[0].ID << b[0].name << b[0].numList[2] << endl; 

    return 0; 
} 

代碼編譯,但它沒有把「臺」字符串轉換成B [0] .name和一個結構元件。分割錯誤在現場發生。

我也在線下試過,但都失敗了。

b[0].name.push_back(dd); 
b[0].name += dd; 

我的編譯器是GCC G ++ 4.7.7 20120313, 和我下面使用編譯命令。

/usr/bin/g++ --std=gnu++0x -Werror -Wall -Wextra -Warray-bounds 

任何幫助將深表謝意,真誠。

+0

是什麼代碼重現?編譯器錯誤? – Rakete1111

+0

歡迎來到Stack Overflow!這聽起來像你可能需要學習如何使用調試器來遍歷代碼。使用一個好的調試器,您可以逐行執行您的程序,並查看它與您期望的偏離的位置。如果你打算做任何編程,這是一個重要的工具。進一步閱讀:** [如何調試小程序](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)** –

+2

來吧,他提供了一個[ mcve],他的編譯器命令行,並表示他得到了段錯誤。讓我們在這裏輕鬆投票。 –

回答

1

對於空向量,您不能使用下標運算符爲其分配新值。使用成員函數代替push_back

例如

std::vector<ttt> b; 
b.reserve(3); 

//... 

b.push_back(ttt()); 
b.back().ID = 1; 
//... 
2

有兩個誤區:

的情況下直接調用push_back或沒有在構造函數調用初始化它事先分配b[0]

另一個問題的行是

b[0].numList[2] 

因爲你只叫push_back()兩次,和索引是從0開始的。

這將是更好的,直接初始化向量是這樣的:

#include <string> 
#include <vector> 
#include <iostream> 

using namespace std; 

struct ttt { 
    string name; 
    unsigned int ID; 
    vector<unsigned int> numList; 
}; 

int main() { 
    vector<ttt> b{{"Desk", 1, { 3, 4 }}}; 
    cout << b[0].ID << b[0].name << b[0].numList[1] << endl; 
} 

Live Example

0

通過Valgrind的對碼報告的第一個錯誤是

==28307== Conditional jump or move depends on uninitialised value(s) 
==28307== at 0x40154F: void std::vector<unsigned int, std::allocator<unsigned int> >::emplace_back<unsigned int>(unsigned int&&) (vector.tcc:94) 
==28307== by 0x4012D7: std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int&&) (stl_vector.h:933) 
==28307== by 0x400F00: main (39273136.cpp:17) 

雖然這威力似乎有點神祕,有一點經驗表明檢查的參數被初始化。通過代碼看,我們可以看到:

vector<ttt> b; 
    b.reserve(3); 
    b[0].ID = 1; 
    b[0].numList.push_back(3); 

你告訴矢量準備有3個要素,但你從來沒有任何ttt對象添加到它。當您訪問b[0]時,您正在使用未初始化的內存(Valgrind不會投訴b[0].ID的分配,因爲內存已分配並且屬於b - 但調用push_back嘗試讀取可能是隨機垃圾的成員vector)。

明顯的解決方案是emplace_back()(或以其他方式創建)b的元素。

0

當您在矢量上調用reserve()時,它不會創建任何包含類型的實例。它只爲元素分配空間。。因此,當您嘗試訪問向量中的這些位置時,您會收到未定義的行爲。您必須首先將元素推入向量中,或者在嘗試對其進行任何讀取或寫入之前,使用vector<ttt> b(6);之類的調用將它們初始化爲零。

只需編輯一行,您聲明ttt的向量並刪除reserve()調用即可修復此程序。

而且要小心,因爲您嘗試訪問b[0].numList[2],該第三元素,但你只能做push_back的兩個元素。

#include <vector> 
#include <string> 
#include <iostream> 

using namespace std; 

struct ttt { 
    string name; 
    unsigned int ID; 
    vector<unsigned int> numList; 
}; 

int main() { 
    vector<ttt> b(3); //create 3 zero-init elements in vector b 
    b[0].ID = 1; 
    b[0].numList.push_back(3); 
    b[0].numList.push_back(4); 
    string dd ("Desk"); 
    b[0].name = dd; 
    cout << b[0].ID << b[0].name << b[0].numList[2] << endl; 
              //^beware, this hasn't been initialized 
    return 0; 
} 

輸出:1Desk0