2015-02-09 52 views
0

所以我有一個項目,旨在讓用戶輸入一個選項上取決於矢量將使用它的類型,即vector<int>vector<float>vector<double>的std ::矢量內存問題

要做到這一點,我創建了3種功能,這將取決於被調用,它的工作原理是這樣的:

#include <iostream> 
    #include <vector> 

    using namespace std; 
    typedef vector<int> intv; 
    typedef vector<float> flov; 
    typedef vector<double> douv; 
    intv vectori(int opt, int t); 
    flov vectorf(int opt, int t); 
    douv vectord(int opt, int t); 

    int main(){ 
    int opt; 
    size_t t; 
    cout << "Size: \n"; 
    cin >> t; 
    cout << "Option? \n"; 
    cin >> op; 
    flov vf; 
    douv vd; 
    intv vi; 
    switch (op){ 
      case 00: 
        vi.reserve(t); 
        vi=vectori(0,t); 
        break; 
      case 01: 
        vf.reserve(t); 
        vf=vectorf(0,t); 
        break; 
      case 02: 
        vd.reserve(t); 
        vd=vectord(0,t); 
        break; 

        } 
    } 

這將是例如vectori功能:

intv vectori(int op, int t) 
{ 
intv v; 
v.reserve(t); 
// Do stuff 
return v; 
} 

而示例vectorf函數是類似的(因此是vectord):

flov vectorf(int op, int t) 
{ 
flov v; 
v.reserve(t); 
// Do stuff 
return v; 
} 

所以問題是:

  • 什麼說法矢量VF的內存成本,考慮到如果不需要的話,我沒有爲它預留的內存。
  • 變量v一旦函數vectorx結束會發生什麼?是否返回v並調用它vi在內存中創建v的副本?
  • 這是整體記憶效率?
+2

'reserve'您使用的方式太多,有些是多餘的,這不會有幫助。更好的是你分析它並親眼看到。如果不運行它,沒有辦法預測效率。那些通過查看代碼來預測的人只是自欺欺人。 – DumbCoder 2015-02-09 09:30:21

+0

爲什麼要在'case'中使用八進制? – 2015-02-09 10:48:53

+0

不是真的,我已經複製了一小部分代碼,使用八進制作爲演示目的。 (使用cout時)。 – D1X 2015-02-10 12:26:28

回答

1

什麼說法矢量vf的內存成本,考慮到如果不需要的話,我沒有爲它預留的內存。

(我假定你的意思是flov vf;聲明)。作爲一般指導原則,內存使用量將大致爲sizeof(the_vector) + sizeof(element_type) * the_vector.capacity()。可能還有更多針對特定實現的調試信息,如果您的實現過於愚蠢,則會增加內存分配頁面大小,同時增加容量......

請注意,std::vector可確保連續內存,意外實現特定的內存浪費是大量不如說std::map,更小,其中內存的支離破碎,每個個體節點可以間接費用分配,調試信息等被打..

與變量v一旦功能會發生什麼vectorx結束?是否返回v並調用它vi在內存中創建v的副本?

用C++ 11可以預期,要麼vi將直接用該數據填充vectorf()名義上返回(由於返回值優化),或者它會被移入構造,這實際上意味着vi將採取存儲向量元素的指針 - 動態分配內存的所有權。它相對輕量級,並且不會因爲處理的元素數量增加而變慢。

因此,在爲它們分配返回的矢量之前,您不應該在vivfvd中保留內存...您最終可能會分配和釋放額外的容量而完全沒有使用它。

整體存儲器是否有效?

對於較大的值t,具有不必要變量的開銷變得微不足道,所以是的。不過要考慮到上面提到的reserve問題 - 因爲在分配過程中您的瞬間內存使用量可能會不必要地過大。


所有這一切說,如果你最終選擇了三種類型的數據之一的程序運行過程中使用,你可能會更好用這樣的一個模板和結構:

#include <iostream> 
#include <vector> 

template <typename T> 
void f(int t) 
{ 
    std::vector<T> v(t); 
    ... do all your work with v... 
} 

int main() 
{ 
    int opt; 
    size_t t; 
    if (std::cout << "Size:\n" && 
     std::cin >> t && 
     std::cout << "Option? \n" && 
     std::cin >> op) 
    { 
     switch (op) 
     { 
      case 00: f<int>(t); break; 
      case 01: f<float>(t); break; 
      case 02: f<double>(t); break; 
     } 
    } 
    else 
     std::cerr << "unable to read inputs from stdin\n"; 
} 
+0

好的,所以我應該做的第一個修改是刪除vi,vf,vd的保留語句。 – D1X 2015-02-09 10:15:16

+0

@ D1X:沒錯 - main()函數中的所有'reverse'語句都會起反作用.... – 2015-02-09 10:17:23

0
  • 對於內存開銷,您需要將其配置爲DumbCoder,這是系統特定的。

  • 變量v是程序本地的,所以它將在程序結束時被釋放。通常返回會創建一個副本,除非編譯器有一些優化。研究「返回值優化」,這是編譯器特有的。

  • 另一種更好的方式做載體傳遞是通過參數引用 無效本功能(標準::矢量& VEC,...)

+0

由於C++ 11具有其移動語義,因此將向量作爲參數傳遞並沒有太多意義。 – Angew 2015-02-09 09:53:30

0

什麼說法vector vf;的存儲成本考慮到如果不需要,我不保留內存。

從技術上講,這取決於標準庫的實現。預先分配一些內存(即,以非零值capacity()開始)將在其權限內。但我不認爲有任何實現實際上它是如果向量然後分配(如你在做什麼)將是非常浪費。

如果你想100%確定,檢查你的標準庫的實現vector::vector(),但我真的希望沒有涉及動態內存分配。

一旦函數vectorx結束,變量v會發生什麼?是否返回v並調用它vi在內存中創建v的副本?

在C++ 11和超越,答案是沒有,沒有多餘的副本。矢量v移動到矢量vi(緩衝區所有權被轉移)。

在C++ 03中,可能會發生副本。如果編譯器足夠聰明,它可能會發現它可以直接在vi中構建返回的矢量,但我擔心它可能太大了一個心理跳躍。可以肯定的是,檢查裝配。

整體存儲器是否有效?

是的,不太可能有任何未使用的堆內存參與。而對象本身可能只佔用堆棧上的3個指針大小。

除此之外:DumbCoder在您的代碼—上指出和vi和相似向量的呼叫存在嚴重缺陷。這些做沒什麼來幫忙。矢量要麼獲得v緩衝區的所有權(在C++ 11中移動),要麼它知道要分配多少內存(v.size()),所以不會有不必要的重新分配。 reserve()只有在您期望多次添加到向量(例如,調用push_back()循環)時纔有意義,並且不希望在此期間發生不必要的重新分配。

1

語句向量vf的內存成本是多少,考慮到我是 ,如果不需要,它不會爲它保留內存。

標準未指定容器的初始容量應該是什麼,所以你依靠執行(見Initial capacity of vector in C++

反正很多實現將從零開始的能力。

一旦函數vectorx結束,變量v會發生什麼? 返回v並調用它vi在內存中創建v的副本?

這取決於編譯器。最新的編譯器將應用Return Value Optimization或使用移動構造函數(請參閱How to "return an object" in C++?C++ vector, return vs. parameter)。

整體存儲器是否有效?

我覺得可以改進。

  1. 你使用reserve太多
  2. 你可以簡化具有一個變體類型的代碼(如見boost variant)。