2014-11-25 58 views
1

我無法從字符串創建向量。有人能解釋下面4種情況的區別嗎?據cplusplus.com我預計Case 1工作相同的Case 2做同樣的奇怪的原因,但它沒有。字符串向量轉換拋出std :: bad_alloc

typedef std::vector<uint8_t> uint8vec_t; 

std::string keySecret() 
{ 
    return std::string ("SomeSecret"); 
} 

案例1

// throws std::bad_alloc 
uint8vec_t vSecret (keySecret().begin(), keySecret().end()); 

案例2

// results in a vector with strange length 
uint8vec_t vSecret (keySecret().begin(), keySecret().begin() + keySecret().length()); 

案例3

// throws std::bad_alloc 
uint8vec_t vSecret (&keySecret()[0], &keySecret()[keySecret().length()]); 

案例4

// throws std::bad_alloc 
uint8vec_t vSecret (&keySecret()[0], &keySecret()[0] + keySecret().length()); 
+2

你的間距是......呃......讓我們稱之爲......非傳統的(並且令人難以置信的混淆閱讀)。 – rubenvb 2014-11-25 14:44:41

+1

@rubenvb,它是GNU風格,http://www.gnu.org/prep/standards/standards.html#Formatting,但我不喜歡C++的所有 – 2014-11-25 14:46:44

回答

7

他們都很糟糕,你只是在第二種情況下碰巧看到了正確的行爲。問題是keySecret每次都返回一個不同的std::string對象。你不能在另一個上呼叫begin,在另一個上呼叫end,並且期望它們以任何方式相關。

您應該調用keySecret一次,製作本地副本,然後在該單個本地對象上調用beginend

+0

Ouw哇,這非常有道理* doh * 。 tyvm! – Ben 2014-11-25 14:34:33

3

兩個呼叫keySecret()之後,你有內存中的兩個不同的字符串:

...x..x....SomeSecret\0..x.x.x...x..x..x.x...SomeSecret\0....x.x..x.x.. 
     ^  ^     ^  ^
      begin1 end1     begin2 end2 

然後,您將嘗試使用來創建矢量要麼

vector<char> v(begin1, end2); 

vector<char> v(begin2, end1); 

(取決於哪個字符串碰巧在內存中更早,哪個字符串由哪個返回致電)。

第一個將分配end2 - begin1字節並將"SomeSecret\0..x.x.x...x..x..x.x...SomeSecret\0"複製到該內存中,兩個迭代器之間的任意字節數包含字符串之間內存中的任何內容。這是未定義的行爲,因爲讀取了爲第一個字符串分配的內存的末尾。

第二個將試圖找到距離end1 - begin2是負的,所以換到非常大的無符號數,並試圖分配很多字節失敗,拋出一個異常bad_alloc

在這兩種情況下,對指向不同對象的兩個不相關指針執行指針算術是未定義的行爲,因此理論上任何事情都可能發生。在實踐中,結果可以像上面那樣在邏輯上得到相當的解釋(儘管段錯誤對於第一種情況而言並不是令人驚訝的結果,而不是具有錯誤內容的向量)。

相關問題