我花了一些時間尋找答案,但沒有找到任何令人滿意的東西。C++:替代矢量引用以避免複製大數據
只是對一些經驗豐富的C++人如何解決這類問題感興趣,因爲現在我正在做的是比原型更多的與生產相關的編碼。
假設你有一個擁有大量數據(比如說500Mb)的unordered_map(hashmap)的類。你想寫一個訪問器,以有效的方式返回這些數據的一部分。
進行以下操作,其中BigData是一些存儲適量數據的類。
Class A
{
private:
unordered_map<string, BigData> m_map; // lots of data
public:
vector<BigData> get10BestItems()
{
vector<BigData> results;
for (........ // iterate over m_map and add 10 best items to results
// ...
return results;
}
};
訪問者get10BestItems因爲它首先複製項的結果矢量,然後將結果矢量時該函數返回(從功能堆複製)複製不在此代碼非常有效的。
你不能在C__因各種原因引用的一個載體,這將是顯而易見的答案:
vector<BigData&> results; // vector can't contain references.
您可以創建堆上的結果向量,並傳遞給一個參考:
vector<BigData>& get10BestItems() // returns a reference to the vector
{
vector<BigData> results = new vector<BigData>; // generate on heap
for (........ // iterate over m_map and add 10 best items to results
// ...
return results; // can return the reference
}
但是,如果你不小心,你會遇到內存泄漏問題。它也很慢(堆內存),並仍然將數據從地圖複製到矢量。
因此,我們可以在C風格的編碼回頭,只是使用指針:
vector<BigData*> get10BestItems() // returns a vector of pointers
{
vector<BigData*> results ; // vectors of pointers
for (........ // iterate over m_map and add 10 best items to results
// ...
return results;
}
但是大多數的消息來源說,不使用指針,除非絕對必要。有些選項可以使用smart_pointers和boost ptr_vector,但我寧願儘量避免這些。
我不認爲地圖會變成靜態的,所以我不太擔心壞指針。只有一個問題,如果代碼將不得不處理指針。在風格上,這是不愉快的:
const BigData& getTheBestItem() // returns a const reference
{
string bestID;
for (........ // iterate over m_map, find bestID
// ...
return m_map[bestID] ; // return a referencr to the best item
}
vector<BigData*> get10BestItems() // returns a vector of pointers
{
vector<BigData*> results ; // vectors of pointers
for_each ........ // iterate over m_map and add 10 best items to results
// ...
return results;
};
例如,如果你想單個項目,那麼很容易返回一個引用。
最後的選擇是簡單地讓哈希地圖公共和返回鍵的矢量(在這種情況下字符串):
Class A
{
public:
unordered_map<string, BigData> m_map; // lots of data
vector<string> get10BestItemKeys()
{
vector<string> results;
for (........ // iterate over m_map and add 10 best KEYS to results
// ...
return results;
}
};
A aTest;
... // load data to map
vector <string> best10 = aTest.get10BestItemKeys();
for (.... // iterate over all KEYs in best10
{
aTest.m_map.find(KEY); // do something with item.
// ...
}
什麼是最好的解決辦法嗎?速度很重要,但我希望能夠輕鬆開發和安全的編程實踐。
「爲了避免複製大數據」 - 那麼可能是一個**引用**引用向量? – 2013-02-08 17:46:13
這與您的問題沒有直接關係,但正如您所說的,get10BestItems()並不是非常有效,我相信您可以將時間複雜度降低到$ O(K)+ O(N \ log K)$和空間複雜度爲$ O(K)$,其中$ N $是元素的數量,$ K = 10 $。您可以使用堆來保留10個最佳值,並使用比較函數來比較兩個不同的值。你可以在這裏看到我的意思的實現:https://github.com/lakshayg/collections/blob/master/algos/ksmallest.cpp – 2016-07-01 08:46:56