std::vector::emplace() 实现中发生了什么?

What is happening in std::vector::emplace() implementation?

提问人:fettahyildiz 提问时间:3/1/2023 最后编辑:Yksisarvinenfettahyildiz 更新时间:3/1/2023 访问量:106

问:

我实现自己的向量类只是为了练习我的 C++ 技能,我的 emplace() 方法比 std::vector::emplace() 慢得多,所以我检查了源代码以查看他们是如何实现它的,但这对我来说只是痛苦。我无法理解这个实现。我还发现实现有点难以阅读,但可能只是我。

这是我从源代码中得到的。

template<typename _Tp, typename _Alloc>
     template<typename... _Args>
       typename vector<_Tp, _Alloc>::iterator
       vector<_Tp, _Alloc>::
       emplace(iterator __position, _Args&&... __args)
       {
     const size_type __n = __position - begin();
     if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
         && __position == end())
       {
         this->_M_impl.construct(this->_M_impl._M_finish,
                     std::forward<_Args>(__args)...);
         ++this->_M_impl._M_finish;
       }
     else
       _M_insert_aux(__position, std::forward<_Args>(__args)...);
     return iterator(this->_M_impl._M_start + __n);
       }

这段代码到底发生了什么?

我的初学者 c++ 直觉告诉我,当 size == capacity 时,然后创建新的动态数组,将所有对象移动到新创建的数组中,在迭代地址更改值并记住已删除的对象,将下一个对象替换为已删除的对象,然后就这样。

C++ 矢量 std emplace

评论

0赞 apple apple 3/1/2023
当然,您应该关注并了解它作为 IMPLementation 的作用。_M_impl
0赞 Fareanor 3/1/2023
你需要更进一步,看看成员实现和它的成员函数的作用(你可能会在某个时候在那里找到某种新的放置)。参数是使用完美转发传递的,正如你在这里看到的。_M_implconstruct()
1赞 user253751 3/1/2023
它说:当在末尾插入一个新元素并且有空间时,然后在那里构造它。否则,调用 _M_insert_aux,这可能是一个更复杂的插入函数,可以处理所有其他情况。是的,由于某种原因,标准库代码总是难以阅读。不知道为什么。问问写它的人。
0赞 fettahyildiz 3/2/2023
@appleapple 这就是我实际上陷入困境的地方,我无法遵循_M_impl和_M_insert_aux方法

答:

3赞 Sam Varshavchik 3/1/2023 #1

你的“初学者C++直觉”是正确的,只是其中大部分实际上并没有发生在这里。

     if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
         && __position == end())

这是将迭代器带到放置新对象的位置的重载。这将检查放置位置是否位于向量的末端,并且向量尚未达到其容量,如果是这样,则可以在向量的 derrière 中就地构造新值,否则:emplace()

 _M_insert_aux(__position, std::forward<_Args>(__args)...);

这将调用另一个函数,在该函数中发生您描述的所有工作,这涉及将向量中的所有现有值在插入位置上或之后移动 1 和/或放大向量。所以,你描述的所有有趣的事情都发生在那边,而不是在这里。

这只是一个简单的情况,其中 emplace 在向量的末尾处理业务,并且向量有增长空间。否则,去那边,看看真正的工作在哪里发生。

这里发生的唯一另一件事是锦上添花:在说完所有事情并完成之后,这个函数在向量中找出新放置值的迭代器,并返回它,因为它需要这样做。

评论

0赞 fettahyildiz 3/2/2023
非常感谢,编码人员发现标准库难以阅读是很常见的吗?如果是这样,为什么会这样?
0赞 Sam Varshavchik 3/2/2023
对于编码人员来说,发现任何大型、复杂的库代码都难以理解是很常见的。