[英]What's the fastest way to reinitialize a vector?
將大向量的所有值重置為其默認值的最快方法是什么?
struct foo
{
int id;
float score;
};
std::vector<foo> large_vector(10000000);
最簡單的方法是創建一個新的向量,但是我想重新分配內存要比重新初始化一個現有的向量花費更多的時間?
在重置之前,我必須遍歷向量以收集非零分數(可能是數千或數百萬)。 我應該在此循環中逐個重置結構嗎?
編輯:
向量大小是固定的,對於每個結構成員(所有浮點數和整數),“默認值”表示0。
重新初始化向量的最快方法是什么?
別。
只需通過調用clear()
記錄矢量沒有有效條目的事實。 這具有既(可能)是最佳的又保證正確的優點,並且還具有完美的表現力。 國際海事組織(IMO)除非概要分析顯示實際需要,否則不考慮任何建議的替代方法。
您的元素類型微不足道,因此對於良好的質量實現,復雜度的線性上限實際上應該是恆定的-無需依次銷毀每個元素。
沒有釋放內存,或者以后需要重新分配內存。
在clear()
后寫入向量時,只需使用push_back
或emplace_back
,而不是使用operator[]
。
為了使它與第一次使用保持一致,請不要使用10000000個值構成的元素初始化向量,而應使用reserve(10000000)
進行預分配而不進行初始化。
例如。
int main() {
vector<foo> v;
v.reserve(10000000);
while(keep_running) {
use(v);
v.clear();
}
}
// precondition: v is empty, so
// don't access v[i] until you've done
// v.push_back({id,score})
// at least i+1 times
void use(vector<foo> &v) {
}
由於您需要就地將元素歸零,因此第二快的通用解決方案可能是將上述循環更改為
while(keep_running) {
v.resize(10000000);
use(v);
v.clear();
}
或者,也可以刪除clear()
並使用fill()
就地覆蓋所有元素。
如果非零元素稀疏(例如,基於某些有意義的索引更新它們),則在主循環遍歷矢量時,將它們動態歸零可能會更快。
同樣,您確實需要進行概要分析,以找出哪種方法更適合您的用例。
將大向量的所有值重置為其默認值的最快方法是什么?
取決於其“默認值”中的向量的含義。
如果要刪除所有元素,最有效的方法是std::vector::clear
。
如果您想將所有元素保留在向量中但設置其狀態,則可以使用std::fill
:
std::fill(large_vector.begin(), large_vector.end(), default_value);
如果元素類型不重要,並且“默認值”為零† ,則std::memset
可能是最佳的:
static_assert(std::is_trivially_copyable_v<decltype(large_vector[0])>);
std::memset(large_vector.data(), 0, large_vector.size() * sizeof(large_vector[0]));
要驗證std::memset
值得std::memset
這個麻煩,您應該測量(或檢查程序集)。 優化器可以為您完成工作。
†零,表示所有位均未設置。 C ++不保證這是零浮點數的表示。 如果您的非最小用例使用了指針,它也不能保證它是一個空指針。
為了確定最快的方法,您將需要運行一些基准測試。
有很多不同的方法可以“重新初始化”向量:
clear()
,對於普通類型,這應該大致等同於執行vector.size = 0
。 向量的容量不變,沒有元素被釋放。 析構函數將在存在的元素上調用。 當您push_back
, emplace_back
或resize
向量resize
,舊值將被覆蓋。 assign()
,例如large_vector.assign( large_vector.size(), Foo() );
。 這將遍歷整個向量,將每個元素重置為其默認值。 希望編譯器將設法將此優化為內存集或類似的集。 0
那么您應該可以執行一個memset
,例如: memset( large_vector.data(), 0, sizeof(Foo)*large_vector.size() );
。 std::fill
例如std::fill( large_vector.begin(), large_vector.end(), Foo() );
,這應該類似於assign
或memset
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.