繁体   English   中英

在MSVC中实现std :: vector :: push_back

[英]Implementatnion of std::vector::push_back in MSVC

我探索了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;
        }
    }

我有一个问题:是检查

if(_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]只是在正确的位置复制构造。

但是如果向量必须重新分配会发生什么? 在这种情况下,传递给push_backv[0]的引用在重新分配之后就会失效,因此push_back将尝试在向量内部复制一个不再存在的对象。

您发布的实现中的代码通过检查引用是否指向向量内的元素来避免问题,在这种情况下,它会记录其索引。 重新分配后,即使引用无效,索引仍然正确,因此可以无风险地执行复制。

两个代码路径中的代码完全不同:

construct(this->_Mylast, this->_Myfirst[_Idx])

相比:

construct(this->_Mylast, _Val)

原因当然是如果向量的容量耗尽,则需要重新分配其存储,这会使引用无效。

如果参数_Val不是向量的一部分,那么它没有相关性,但如果 ,那么我们在重新分配后就不能再使用它了。 因此,在第一个代码路径中, _Val是向量的一部分,该值由其向量索引而不是原始函数参数引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM