簡體   English   中英

STL矢量性能

[英]STL vector performance

每次調用push_back時,STL向量類都使用復制構造函數存儲對象的副本。 它不會減慢程序的速度嗎? 我可以有一個自定義鏈表的類來處理指向對象的指針。 雖然它不會有STL的一些好處,但仍然應該更快。

請參閱以下代碼:

#include <vector>
#include <iostream>  
#include <cstring>

using namespace std;

class myclass
{
    public:
        char* text;

        myclass(const char* val)
        {
           text = new char[10]; 
           strcpy(text, val);
        }

        myclass(const myclass& v)
        {
            cout << "copy\n";
            //copy data
        }
};

int main()
{
    vector<myclass> list;
    myclass m1("first");
    myclass m2("second");

    cout << "adding first...";
    list.push_back(m1);

    cout << "adding second...";
    list.push_back(m2);

    cout << "returning...";
    myclass& ret1 = list.at(0);
    cout << ret1.text << endl;

    return 0;
}

它的輸出如下:

adding first...copy
adding second...copy
copy

輸出顯示復制構造函數在添加時和在檢索值時都被調用。 當我們有更大的對象時,它對性能esp有什么影響嗎?

復制會影響性能。 如果將大對象保留在標准容器中,最好使用智能指針而不是對象本身。

其他海報沒有提到的東西是你可以使用vector :: reserve來預先分配矢量的內存區域,如果你知道你的矢量需要多少元素。 這應該可以加快速度,特別是如果你使用push_back來按值存儲對象,因為當向量類遇到循環中的容量限制時,它不必重新分配新的連續內存塊。

是的,它確實。 這是我們在C ++ 0x中獲得右值引用的主要原因之一。

除非您存儲基本類型,否則建議使用指針作為向量元素而不是實際對象本身。 在許多情況下,更好地使用智能指針。
復制ctor仍然會被調用 - 不是你的類,而是智能指針類。

這一切都取決於你的對象有多大..但我會說大多數時候最好使用值語義(復制整個對象),它應該足夠高性能。 它使您不必考慮與指針相關的內存管理。

只有當你發現性能不夠時才考慮使用指針然后仔細處理內存管理。

如果你需要指針,只需使用vector<myclass*>而不是推出自己的集合類。 這是STL的通用美=)

在C ++ 0x的注釋中,std :: vector和friends將獲得emplace_back(),它將元素放置到向量的末尾。

http://msdn.microsoft.com/en-us/library/dd647620.aspx

您可能不相信它,但vector (更好的仍然是deque )是STL為大多數任務提供的最快的容器。

您可能會擔心復制對象,但除非它非常龐大或復制構造函數有點復雜,否則復制在堆上分配它的對象的成本會更低。

堆分配和結果緩存未命中比簡單復制更具懲罰性。

但是,讓我們不要在空閑的談話中嬉戲:將你的容器與vector對比,看看哪個是最重要的,以及按照哪個數量級,我打賭你會感到驚訝。

如果真的你的類很大或者禁止復制,總會有boost::ptr_vector ,但是除非你使用一個池,否則你顯然會在窗口拋出緩存局部性;)

復制會對性能產生一些影響。 對於小對象,只需按值存儲它們,並且分析將告訴您是否需要重新考慮。 對於較大的對象,您可以在容器中存儲智能指針以減輕一些問題。 同樣,如果通過值存儲對象是自然的,那就這樣做,除非分析表明它是一個重要的瓶頸。

另請注意,我不相信回報實際上是在制作副本。 你所看到的是“添加第二個”可能會產生兩個副本:首先,它必須將矢量從1擴展到(可能)2,並將舊元素從其先前位置復制到新元素,然后復制元素2到位。

復制對象可能會產生不可預見的副作用。 實際情況是C ++類通常不會被復制,因此可能會導致錯誤...理想主義者會爭辯說“他們應該正確編寫他們的課程”但我更願意在現實中處理,它甚至不會那么罕見發生。 更不用說你的課程中創建/破壞的任何記錄都會發生很多事情。

從根本上說,這不是編碼器意味着發生的事情,而是制作副本。 僅這一點意味着它對於非平凡類型來說是一個糟糕的計划。 對於簡單的情況,它很好(比如一個Point2D類)但要小心,一般來說,如果類沒有攜帶少量數據,則存儲指針(或使用智能指針)。

您應該為您的用例選擇具有最佳性能特征的容器。 您的用例看起來需要將項目添加到容器的背面。 使用vector ,除非事先知道成員的最大數量並且能夠提前reserve ,否則有時會獲得重新分配和性能損失。

相反,如果使用deque則可以保證在容器的后面(或前面)插入恆定時間,同時仍保留有用的功能,例如隨機訪問。

如果你想要一些語義上的東西變成一個指針向量的東西純粹出於性能原因不是我的建議,實際上它可能不是一個性能增益,因為每個對象需要一個單獨的內存分配,而不像使用一個容器的對象可以預先分配多個對象的存儲器。

首先,建議使用指針,而不是在向量中使用自己的類。 但是這里數據text存儲為指針。 它(文本屬性的值)沒有被復制兩次。所以在這個應用程序中沒有重大的性能問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM