簡體   English   中英

安全使用+ =運算符使用[]創建一個新的std :: map條目?

[英]Safe to use += operator to create a new std::map entry using []?

假設我有一個std::map<int, int> ,這樣做是否安全?

std::map<int, int> m_map;
m_map[0] += 1;

如果我執行此操作時地圖中不存在鍵0 ,它將如何知道要添加1值是什么?

我希望std :: map通過在值在地圖中創建新條目的情況下執行=而不是+=來處理此問題。 這將使我不必這樣做:

std::map<int, int>::iterator it = m_map.find(0);
if(it != m_map.end()) {
    it->second += 1;
}
else {
    m_map[0] = 1;
}

由於先前未映射的鍵而在調用operator[]插入到映射中的元素是值初始化的 如果您沒有看到該語法,請考慮()在以下代碼段中的特殊含義。 parens很重要。 它們在初始化樹中引入了與默認初始化不同的行程。 兩者都很重要; 兩者都按語言標准列出。

int i = int();

事實證明,標量(包括指針)的值初始化最終會屈服於零初始化 雖然很奇怪,但先前的片段值初始化了一個int實例,由於int是標量,因此它變為零初始化,然后將其復制到i (公平地說,幾乎肯定會有一些消失,但基本面也是如此)。

無論如何,由於該功能,您可以放心:

m_map[0] += 1;

甚至這個:

++m_map[0];

如果索引未事先映射,則會添加一個值初始化元素,這將為標量零初始化,這意味着您將正式開始為零

值得一提的是,對於具有隱式聲明的構造函數的任何類型 ,都會發生類似的活動。 無論是否瑣碎,都會發生一些有趣的事情。

struct S { int a; int b; };
std::map<int, S> mymap;

++mymap[0].a;

a映射到構件0在我們的容器可靠地1以上執行后? 是的 ,確實如此。 此外,考慮一下:

struct S { int a; std::string str; };
std::map<int, S> mymap;

++mymap[0].a;

現在S有一個非平凡的隱式構造函數(它必須,因為它必須構造str )。 但是,在我們的容器中映射到0 a成員是否仍然可靠地進行了零初始化(因此在上述行之后為1 )? 是的 ,確實如此。

如果對引用的不同初始化路徑感到好奇, 請參閱此問題和答案 或者回顧一下C ++ 11標准,特別是C ++11§8.5Initializers,(p5,p7,p10) 值得一讀。

保證即使使用較短的代碼段也能獲得1分。

關鍵是operator[]必須返回對它的引用之前在地圖中創建元素,所以當你需要+=元素已經存在時,如果必須現在創建它,則值為零(因為地圖的元素是價值初始化的)。

(順便說一句,這就是為什么當你使用帶有類類型的std::map作為值時,如果你想使用operator[] ,它必須有一個默認的構造函數,即使你立即為它指定了一個對象)

是的,這很好,新條目默認值為value_type() ,對於int0

它仍然是+= ,但0 += 1給出1

Map使用默認構造函數初始化。(所有int為零)

因此它在地圖中不存在0 ,它將被初始化為包含值0,並且在+= 1之后將添加+= 1

所以你可以使用更高版本的代碼而不用擔心。

cplusplus.com 調用map_obj [k]的引用效果

如果k匹配容器中元素的鍵,則該函數返回對其映射值的引用。

如果k與容器中任何元素的鍵不匹配,則該函數將使用該鍵插入一個新元素,並返回對其映射值的引用。 請注意,即使沒有為元素指定映射值(使用其默認構造函數構造元素),這也會將容器大小增加1。

暫無
暫無

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

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