簡體   English   中英

std :: vector :: reserve是否保證在這種情況下實現不會使迭代器失效?

[英]Does std::vector::reserve guarantee that the implementation will not invalidate iterators in this case?

這是一個打算:

a)接受int的向量

b)對於輸入向量中的每個int,追加此int的逆

先決條件:無

postconditions:返回vector的size()是2 *輸入向量的大小。

請注意,矢量是就地修改的。

題:

在變換期間,此函數是否嚴格定義了與迭代器失效相關的行為?

獎金:

是否有更好/更簡潔/更健壯的方式來編寫它?

碼:

std::vector<int> append_negatives(std::vector<int> v)
{
    v.reserve(v.size() * 2);
    std::transform(begin(v), end(v), 
                   back_inserter(v), 
                   [](auto&& x) { return -x; });
    return v;
}

只要您不超過預分配容量,就不會發生重新分配,也不會使引用矢量項的引用或迭代器失效。 但是,由於end()返回的迭代器不引用任何向量項,因此它可能仍會失效。

23.3.11.3載體容量[vector.capacity]

  1. ...在調用reserve()之后發生的插入期間不應進行重新分配,直到插入使向量的大小大於capacity()的值reserve()為止

...

23.3.11.5向量修飾符[vector.modifiers]

  1. ...如果沒有重新分配,插入點之前的所有迭代器和引用仍然有效。

關於迭代器失效規則的部分已經被涵蓋了,所以我將借此機會謙虛地質疑是否需要使用所有這些機制(以其微妙的規則)來處理這樣一個微不足道的問題。 你也可以認為這是一個刺

獎金:

是否有更好/更簡潔/更健壯的方式來編寫它?

部分問題。


老實說,我完全用for循環的先進技術來回避這個問題。

std::vector<int> append_negatives(std::vector<int> v) {
    size_t sz = v.size();
    v.resize(sz*2);
    for(size_t i = 0; i < sz; ++i) v[i+sz] = -v[i];
    return v;
} 

並非所有內容都必須在深層的STL算法中進行混淆。 這個更短,IMO更具可讀性,並避免了迭代器失效的麻煩。

此外,除非編譯器自上次檢查以來已經獲得了額外的智能,否則這要快得多,因為避免了push_back所有開銷(檢查容量是否足夠以及每次迭代時的增量大小),這被替換為直接指針訪問( 一個程序集)指令); 纖細而簡單的環體為自動展開提供了更好的機會。 我希望編譯速度更快,因為我們避免實例化一堆模板。

請注意,即使使用transform benemoth,也可以獲得速度優勢/無失效頭痛:

std::vector<int> append_negatives(std::vector<int> v) {
    size_t sz = v.size();
    v.resize(sz * 2);
    auto beg = begin(v);
    std::transform(beg, beg + sz, beg + sz, 
                   [](int x) { return -x; });
    return v;
}

但我沒有看到這種過於冗長的代碼優於普通for循環的任何優勢,除非你得到你設法擠入代碼的“酷”C ++功能的數量。


@MikeMB詢問默認構造成本高昂的類型; 在這種情況下,顯式push_back很好:

std::vector<int> append_negatives(std::vector<int> v) {
    size_t sz = v.size();
    v.reserve(sz*2); // optional
    for(size_t i = 0; i < sz; ++i) v.push_back(-v[i]);
    return v;
}

如果原始帖子中的transform有效,您還可以使用基於范圍的for循環:

std::vector<int> append_negatives(std::vector<int> v) {
    v.reserve(v.size()*2);
    for(int &x: v) v.push_back(x);
    return v;
}

這是對眼睛比基於變換的解決方式更好,但我有還是沒有關於結束迭代器失效一致的意見看,所以這將是同樣無效。

暫無
暫無

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

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