我探索了msvc 2013 STL实现,并发现了std :: vector :: push_back的以下实现:
void push_back(const value_type& _Val)
{ // insert element at end
if (_Inside(_STD addressof(_Val))) // <-- is this check really necessary?
{ // push back an element
size_type _Idx = _STD addressof(_Val) - this->_Myfirst;
if (this->_Mylast == this->_Myend)
_Reserve(1);
this->_Getal().construct(this->_Mylast,
this->_Myfirst[_Idx]);
++this->_Mylast;
}
else
{ // push back a non-element
if (this->_Mylast == this->_Myend)
_Reserve(1);
this->_Getal().construct(this->_Mylast,
_Val);
++this->_Mylast;
}
}
我有一个问题:是支票
如果(_Inside(_STD addressof(_Val)))
真的必要吗?此条件检查_Val是否属于此向量。例如,在以下情况下,此条件成立:
std::vector<int> v(1);
v.push_back(v[0]);
相同向量的元素的push_back和其他值之间有什么区别?
我不知道该标准是否要求进行额外的检查,但是它避免了将自身元素推入向量时可能发生的细微错误。
假设您这样做,如您的示例所示,
std::vector<int> v(1);
v.push_back(v[0]);
在不执行该检查的实现中。现在,如果向量的容量大于1,则一切都很好,v[0]
只是在正确的位置进行了复制构造。
但是,如果必须重新分配向量,会发生什么?在这种情况下,v[0]
传递给该对象的引用将push_back
在重新分配后立即失效,因此push_back
将尝试在向量内复制一个不再存在的对象。
您发布的实现中的代码通过检查引用是否指向向量中的某个元素来避免该问题,并且在这种情况下,它会记录其索引。重新分配后,即使引用无效,索引仍然正确,因此可以无风险执行复制。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句