Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ libc++;向量::插入重载之间的区别_C++_C++11_Vector_Libc++ - Fatal编程技术网

C++ libc++;向量::插入重载之间的区别

C++ libc++;向量::插入重载之间的区别,c++,c++11,vector,libc++,C++,C++11,Vector,Libc++,libc++的std::vector具有以下insert重载: template <class _Tp, class _Allocator> typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { pointer __p = this->__begin_

libc++的
std::vector
具有以下
insert
重载:

template <class _Tp, class _Allocator>
typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
{
    pointer __p = this->__begin_ + (__position - begin());
    if (this->__end_ < this->__end_cap())
    {
        __RAII_IncreaseAnnotator __annotator(*this);
        if (__p == this->__end_)
        {
            __alloc_traits::construct(this->__alloc(),
                                      _VSTD::__to_raw_pointer(this->__end_), __x);
            ++this->__end_;
        }
        else
        {
            __move_range(__p, this->__end_, __p + 1);
            const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
            if (__p <= __xr && __xr < this->__end_) // [*]
                ++__xr;
            *__p = *__xr;
        }
        __annotator.__done();
    }
    else
    {
        allocator_type& __a = this->__alloc();
        __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
        __v.push_back(__x);
        __p = __swap_out_circular_buffer(__v, __p);
    }
    return __make_iter(__p);
}
模板
类型名向量::迭代器
向量::插入(常量迭代器位置,常量引用x)
{
指针uuu p=this->uuuu begin+(uuu position-begin());
如果(此->\uuuuu end\uuu<此->\uuuuu end\u cap())
{
__RAII_递增注释器__注释器(*此);
如果(_p==此->_结束)
{
__alloc_traits::construct(this->alloc(),
_VSTD::uuu到_u原始_指针(此->uuu结束),uux);
++这个->结束;
}
其他的
{
__移动范围(uuu p,此->uuu结束,uu p+1);
常量指针uuxr=指针特性::指针指向(uux);
如果(_p _end)/[*]
++__xr;
*__p=*uuxr;
}
__注释器;
}
其他的
{
分配器类型&uuu a=this->uuu alloc();
__拆分缓冲区(建议使用(大小()+1),\uuuu p-此->\uuu开始,\uuu a);
__v、 向后推(x);
__p=uuu交换u输出u循环u缓冲区(uuu v,uu p);
}
返回(make)iter(p);;
}
。。。和类似的,取右值引用:

template <class _Tp, class _Allocator>
typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x)
{
    pointer __p = this->__begin_ + (__position - begin());
    if (this->__end_ < this->__end_cap())
    {
        __RAII_IncreaseAnnotator __annotator(*this);
        if (__p == this->__end_)
        {
            __alloc_traits::construct(this->__alloc(),
                                      _VSTD::__to_raw_pointer(this->__end_),
                                      _VSTD::move(__x));
            ++this->__end_;
        }
        else
        {
            __move_range(__p, this->__end_, __p + 1);
            *__p = _VSTD::move(__x);
        }
        __annotator.__done();
    }
    else
    {
        allocator_type& __a = this->__alloc();
        __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
        __v.push_back(_VSTD::move(__x));
        __p = __swap_out_circular_buffer(__v, __p);
    }
    return __make_iter(__p);
}
模板
类型名向量::迭代器
向量::插入(常量迭代器位置、值类型和x)
{
指针uuu p=this->uuuu begin+(uuu position-begin());
如果(此->\uuuuu end\uuu<此->\uuuuu end\u cap())
{
__RAII_递增注释器__注释器(*此);
如果(_p==此->_结束)
{
__alloc_traits::construct(this->alloc(),
_VSTD::uuu到_u原始_u指针(此->uuu结束),
_VSTD::move(uux));
++这个->结束;
}
其他的
{
__移动范围(uuu p,此->uuu结束,uu p+1);
*__p=_VSTD::move(uux);
}
__注释器;
}
其他的
{
分配器类型&uuu a=this->uuu alloc();
__拆分缓冲区(建议使用(大小()+1),\uuuu p-此->\uuu开始,\uuu a);
__v、 向后推(_-VSTD::move(u-x));
__p=uuu交换u输出u循环u缓冲区(uuu v,uu p);
}
返回(make)iter(p);;
}
在第一个重载中标记为
[*]
的分支的用途是什么?这是标准要求的吗?为什么它在第二个过载中不存在?我在
libstdc++
中找不到等效的构造


编辑
libstdc++
通过创建临时副本来解决相同的问题。

这是处理尝试插入的元素已存在于
向量中的情况的一个条件

为了解释这一点,让我们从定义函数中使用的变量开始

  • \up
    是指向要插入新元素的位置的指针
  • \uxr
    是指向要插入的元素地址的指针
向量
有足够的容量插入额外的元素(
if(this->\uuuu end\uuu\uu end\u cap())
时,将执行您询问的代码路径。此外,插入点不是
end()
迭代器(
if(\uu p==this->\uu end)
-执行
否则的
路径)

在这种情况下,实现首先将范围
[\uu p,end())
中的所有内容再移动一个位置-
\uu移动范围(\uu p,this->\uu end,\uu p+1);

但是,如果您试图插入的元素是刚刚移动的范围的一部分,该怎么办?如果是,您必须增加指向要插入的元素的指针。下面几行就是这样做的

if (__p <= __xr && __xr < this->__end_)
  ++__xr;
if(\uuu p\uu end\uu)
++__xr;
rvalue引用重载没有执行相同的检查,因为允许实现假定rvalue引用引用的任何对象都是唯一引用的,因此尝试使用对向量中已存在的元素的rvalue引用执行插入是未定义的行为

摘自N3337,§17.6.4.9/1【关于论点的决议】

下面的每一个都适用于C++标准库中定义的函数的所有参数,除非明确说明。 -…
-如果函数参数绑定到右值引用参数,则实现可能会假定此参数是此参数的唯一引用


这是上述条款的基本原理。

回答得很好!我忽略了一个事实,即可以插入已经插入的内容。@Ernon我记得我在某个地方读过一篇讨论,这是由于遗漏。标准中没有任何内容告诉你不允许插入已经在同一个v中的元素ector,所以需要实现来支持这种可能性。+1,非常好的解释。我故意违反了评论这项投票的规则,因为我编写了被质疑的代码,以及标准中支持实现的文字。谢谢,现在看起来很好:-)