stl vector push_back解析

查看 Visual Studio 2013的stl vector代碼, 發現push_back要先判斷元素是否本來就在vector裏面,再分情況push_back.

粗看不解,以爲多此一舉,其實裏面暗藏玄機。

所以就搜索一下,發現了這個問題“Is it safe to push_back an element from the same vector?”的討論,https://stackoverflow.com/questions/18788780/is-it-safe-to-push-back-an-element-from-the-same-vector

原來push_back的實現不但沒問題,而且還是修復了可能的bug。就連stl標準委員會的人都曾犯過這種錯誤。

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#526

原因是push_back的時候可能會由於size()==capacity() 導致vector的地址重新分配,這樣指向原vector數據的指針就是無效指針,再訪問這個無效指針就會出問題。

看如下代碼:

vector<int> v;

v.push_bac(1);

v.push_back(v[0]); //在重新分配內存後,v[0]的地址會發生改變,如果還訪問就的v[0]就是非法訪問了。

同理insert等操作也需要先判斷元素地址是否本來就在vector裏面。

附VS2013 STL ,vector的push_back 實現代碼:

 

   void push_back(const value_type& _Val)
        {    // insert element at end
        if (_Inside(_STD addressof(_Val)))
            {    // push back an element
            size_type _Idx = _STD addressof(_Val) - this->_Myfirst;
  
         if (this->_Mylast == this->_Myend)
                _Reserve(1);
            _Orphan_range(this->_Mylast, this->_Mylast);
            this->_Getal().construct(this->_Mylast,
                this->_Myfirst[_Idx]);
            ++this->_Mylast;
            }
        else
            {    // push back a non-element
            if (this->_Mylast == this->_Myend)
                _Reserve(1);
            _Orphan_range(this->_Mylast, this->_Mylast);
            this->_Getal().construct(this->_Mylast,
                _Val);
            ++this->_Mylast;
            }
        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章