提问人:fettahyildiz 提问时间:3/1/2023 最后编辑:Yksisarvinenfettahyildiz 更新时间:3/1/2023 访问量:106
std::vector::emplace() 实现中发生了什么?
What is happening in std::vector::emplace() implementation?
问:
我实现自己的向量类只是为了练习我的 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 时,然后创建新的动态数组,将所有对象移动到新创建的数组中,在迭代地址更改值并记住已删除的对象,将下一个对象替换为已删除的对象,然后就这样。
答:
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
对于编码人员来说,发现任何大型、复杂的库代码都难以理解是很常见的。
评论
_M_impl
_M_impl
construct()