C++ 为std::vector编写自定义插入函数

C++ 为std::vector编写自定义插入函数,c++,stdvector,C++,Stdvector,我正在为我的个人项目编写std::vector的插入函数 插入前的矢量布局: position : 0 1 2 3 4 Value : a b c e f 假设有足够的容量,我想在位置3插入'd' 插入后的矢量布局: position : 0 1 2 3 4 5 Value : a b c d e f 我编写了一个函数,将值向右移动到给定的插入位置之后(在本例中为3),然后在请求的插入位置分配给定值 我为shift_right编写的函数如下: template <type

我正在为我的个人项目编写std::vector的插入函数

插入前的矢量布局:

position : 0 1 2 3 4
Value    : a b c e f 
假设有足够的容量,我想在位置3插入'd'

插入后的矢量布局:

position : 0 1 2 3 4 5
Value    : a b c d e f
我编写了一个函数,将值向右移动到给定的插入位置之后(在本例中为3),然后在请求的插入位置分配给定值

我为shift_right编写的函数如下:

template <typename T>
void vector<T>::shift_right(typename vector<T>::iterator given_pos) {
    for (auto iter = end() - 1; iter != given_pos - 1; iter--) {
        *(iter + 1) = *iter;
    }
}

模板
void vector::shift_right(typename vector::迭代器给定位置){
对于(自动iter=end()-1;iter!=给定位置-1;iter--){
*(国际热核实验堆+1)=*国际热核实验堆;
}
}
是否有std::algorithm或其变体可以帮助me摆脱shift\u right函数中的原始循环

您可以使用:


这假设容量已在必要时增加,并且
end()
返回新的结束迭代器(即插入新空格后的最后一个元素后的一个迭代器)。更改为
std::向后移动(给定位置,end()-1,end())如果不是这样的话。

你的意思好像是

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

template <typename T>
typename std::vector<T>::iterator 
shift_right( std::vector<T> &v, typename std::vector<T>::size_type pos )
{
    v.resize( v.size() + 1 );

    typename std::vector<T>::iterator result = std::end( v );

    if ( pos < v.size() )
    {
        result = std::copy_backward( std::next( std::begin( v ), pos ), 
                                     std::prev( std::end( v  )),
                                     std::end( v ) );
    }

    return std::prev( result ); 
}

int main() 
{
    std::vector<int> v;

    auto it = shift_right( v, v.size( ) );

    *it = 2;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    it = shift_right( v, v.size() );
    *it = 3;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    it = shift_right( v, 0 );
    *it = 0;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    it = shift_right( v, 1 );
    *it = 1;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    return 0;
}
请注意,最好使用
std::copy_backward
而不是
std::move_backward
,因为在第一种情况下,向量的所有元素的状态将与基本类型数组的元素在移位后的状态类似

如果要使用
std::move_backward
,则相应的函数可以如下所示,如下面的演示程序所示

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

template <typename T>
typename std::vector<T>::iterator 
shift_right( std::vector<T> &v, typename std::vector<T>::size_type pos )
{
    v.resize( v.size() + 1 );

    typename std::vector<T>::iterator result = std::end( v );

    if ( pos < v.size() )
    {
        result = std::move_backward( std::next( std::begin( v ), pos ), 
                                     std::prev( std::end( v  )),
                                     std::end( v ) );
    }

    result = std::prev( result );
    *result = T();

    return result; 
}

int main() 
{
    std::vector<int> v = { 1, 2, 4, 5, 6 };

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    auto it = shift_right( v, 2 );

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    *it = 3;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    return 0;
}

我首先定义一个方便的函数模板,
right\u shift\u by\u one()
,它将元素在有效的迭代器范围内向右移动一个位置[
first
last
):

此成员函数返回一个迭代器,该迭代器指向通过右移创建的新空间对应的元素。即使向量没有足够的容量,这也会起作用,因为已经考虑了迭代器在重新分配时的无效性。您必须实现
resize()
在您的自定义向量实现中

使用:


我想也许在这里能有所帮助?或者也许和。你应该首先确保有足够的容量来支持向量。我的实现正在工作。我已经确保有足够的容量(也在文章中提到)@Galik我确实查看了rotate。我无法理解如何实现它。您可能需要使用名称空间,例如
my::vector
,以明确您正在编写自己的类
v.resize(v.size()+1)
。也就是说。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

template <typename T>
typename std::vector<T>::iterator 
shift_right( std::vector<T> &v, typename std::vector<T>::size_type pos )
{
    v.resize( v.size() + 1 );

    typename std::vector<T>::iterator result = std::end( v );

    if ( pos < v.size() )
    {
        result = std::copy_backward( std::next( std::begin( v ), pos ), 
                                     std::prev( std::end( v  )),
                                     std::end( v ) );
    }

    return std::prev( result ); 
}

int main() 
{
    std::vector<int> v;

    auto it = shift_right( v, v.size( ) );

    *it = 2;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    it = shift_right( v, v.size() );
    *it = 3;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    it = shift_right( v, 0 );
    *it = 0;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    it = shift_right( v, 1 );
    *it = 1;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    return 0;
}
2 
2 3 
0 2 3 
0 1 2 3
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

template <typename T>
typename std::vector<T>::iterator 
shift_right( std::vector<T> &v, typename std::vector<T>::size_type pos )
{
    v.resize( v.size() + 1 );

    typename std::vector<T>::iterator result = std::end( v );

    if ( pos < v.size() )
    {
        result = std::move_backward( std::next( std::begin( v ), pos ), 
                                     std::prev( std::end( v  )),
                                     std::end( v ) );
    }

    result = std::prev( result );
    *result = T();

    return result; 
}

int main() 
{
    std::vector<int> v = { 1, 2, 4, 5, 6 };

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    auto it = shift_right( v, 2 );

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    *it = 3;

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout <<'\n';

    return 0;
}
1 2 4 5 6 
1 2 0 4 5 6 
1 2 3 4 5 6 
template<typename BidirIt>
void right_shift_by_one(BidirIt first, BidirIt last) {
   std::move_backward(first, std::prev(last), last);
}
template<typename T>
auto shift_right(typename vector<T>::iterator pos) {
   auto dist = std::distance(begin(), pos);

   // this only compiles if T is default constructible
   resize(size()+1);

   // resize() may have invalidated the pos iterator due to vector's reallocation
   // recompute it
   pos = begin() + dist;

   right_shift_by_one(pos, end());
   return pos;
}
auto it = shift_right(vec.begin() + 2);
*it = 'c';