2013-05-02 27 views
3

從我讀到的內容來看,std::vector是在與需要連續內存字節數組的c函數接口時使用的適當結構。然而,我想知道如何在某些情況下確定陣列的大小正確設置std :: vector大小的方法

我寫了一個小樣本程序來說明我的意思。

int main(int argc, char *argv[]) 
{ 
    std::vector<unsigned char>v; 
    unsigned char p[1024]; 

    sprintf((char*)&p[0], "%10d", 10); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 
    v.reserve(30); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 
    memcpy(&v[0], &p[0], 20); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 
    v.reserve(50); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 
    v.reserve(0); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 
    v.resize(20); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 
    v.resize(0); 
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl; 

    return 0; 
} 

的輸出(沒有多少令人驚訝):

Size: 0 Length: 0 
Size: 0 Length: 30 
Size: 0 Length: 30 
Size: 0 Length: 50 
Size: 0 Length: 50 
Size: 20 Length: 50 
Size: 0 Length: 50 

我爲什麼這樣做的原因是這樣的,因爲我預留一定大小的緩衝區,然後通過recv()通過這個內存插槽。由於我必須將內存作爲指針傳遞,因此根據recv返回的值無法調整矢量大小。 現在,當接收到的字節數小於緩衝區時,我會想到我可以以某種方式調整向量的大小,所以當我將它傳回時,調用者可以執行v.size()以及返回的元素數接收。

當我從上面的例子看數據時,當使用resize()緩衝區的大小被正確調整,但數據不見了。那麼我是否真的必須單獨將內存複製到新的矢量中才能獲得正確的大小?這聽起來像是對我來說非常不必要的開銷。或者有什麼方法可以告訴矢量它目前應該保存多少個元素?

回答

5

你正在做錯的順序。

  1. resize您希望緩衝區接受的最大大小。
  2. 存儲數據(它必須小於向量大小)。
  3. resize爲真實的數據大小。

你的「消失的數據」的問題,是因爲當你複製的數據的第一時間,你的矢量沒有大小隻有容量(實際上並沒有使用它來保存數據即預留的內存)。當您再次使用reserve時,大小仍然爲0,因此矢量可以自由優化數據副本,因爲它知道它只能保留第一個元素(即0)。

換句話說:

  • capacity() =多少,你可以把數據以矢量,而不會觸發重新分配。
  • size() =你真的使用了多少數據(和載體將保持只能隔着再分配是數據)

更重要的是,在訪問向量元素超出其當前size()是未定義行爲(可能似乎與積分類型一起工作,但考慮未初始化的對象會發生什麼......)。不要這樣做。

+0

謝謝,這的確是正確答案,我在調試器中用我的testprogram驗證了它。現在我也明白爲什麼。 :)這也適合我的實現模型,因爲我不是在開始時使用構造函數,而是想手動設置大小。 – Devolus 2013-05-02 14:14:03

3

recv直入緩衝區,沿着線的東西:

std::vector< unsigned char > buffer(1024); 
buffer.resize(recv(&buffer[0], buffer.size())); 

取決於是否能recv的返回錯誤代碼,你可能有調整之前辦理入住手續。

+0

這將保證在調整大小期間數據不會丟失?因爲這是我在短文件中用memcpy模擬的內容。當我調用接收時,操作系統會將來自套接字的數據放入緩衝區,我知道這個向量不會有多大。這就是爲什麼我需要在之後調整size(),所以向量知道它擁有多少元素,但顯然它不應該丟失該過程中的數據,這顯然是因爲矢量實現只關心已知元素。 – Devolus 2013-05-02 13:59:59

+0

@Devolus:vector被初始化爲保存1024個元素,所以它已經知道有1024個有效元素('recv'寫在其上); 'resize'只會修正實際使用的元素的元素數量,並且(可能)修剪使用的內存。 – 2013-05-02 14:03:27

+1

@MatteoItalia'resize'不能重新分配,除非它需要,所以它不能使緩衝區變小。在C++ 11中,有一個函數'std :: vector <> :: shrink_to_fit',可以用來減少使用的內存,或者你可以像'std :: vector (v.begin (),v.end()).swap(v);'。 – 2013-05-02 14:32:49

0

v.reserve(n)將容量設置爲n

m = recv(s,&v[0],n,0) 

v.resize(m)將矢量大小設置爲recv得到的值。

+4

如果您之前沒有設置大小,您將永遠無法看到「recv」得到了什麼。 (當然,你還有未定義的行爲。) – 2013-05-02 13:49:23

0

當你從vector的緩衝區第一個字節開始向內存位置複製某些東西時 - 那麼向量不知道這一點,並且不會更新它的內部大小計數器。使用vector的assign()或insert()方法將緩衝區複製到向量中。

reserve()不會減少先前保留的容量。這就是爲什麼在最後一行你仍然看到50然而你減少到20

相關問題