繁体   English   中英

使用迭代器修改c ++中的数组元素

[英]Using iterators to modify array elements in c++

当我尝试编写一个插入函数时会出现问题,该函数假设将数组中的所有元素移动到迭代器给定的指定位置,然后在迭代器给定的位置向数组中插入一个新值。

代码在插入函数中出现错误,并出现以下错误:

'operator []'不匹配(操作数类型是'std :: basic_string [1000]'和'std :: basic_string')

我是新手使用迭代器,我认为不可能使用指针作为索引访问数组元素。 所以我不确定是否有另一种方法可以做到这一点,或者我是否需要重载[]运算符以使其工作如何?

template <class T>
class Vector {
    public:
        typedef T* iterator;
        Vector () {  }

        T& operator[](unsigned int i) {
           return items[i];
        }
          // T& operator[](iterator i) {
           //return items[*i];
        //}

        iterator begin () {
            return &items[0];
        }
        iterator end () { 
            return &items[used];
        }
        int size () { return used; }

        iterator insert (iterator position, const T& item) { 

            for(Vector<T>::iterator i=&items[998]; i>=position; i--)
            {
                items[*(i+1)]=items[*i];
            }
            items[*position]= item;

            return position;
        }
    private:
        T items[1000];
        int used=0;
};

这个代码在某种意义上是有问题的,因为它创建了1000个T类型的元素,即使它在逻辑上是空的。 此外,如果插入次数超过1000次,则丢弃上部元素。

至于编译问题,我尝试使用Vector<int>编译代码,它编译得很好,但崩溃了。 出于同样的原因,它与Vector<int>崩溃,它不能使用Vector<std::string>编译。 问题是与类型*i ,这一点,即, std::string中的情况下, Vector<std::string> 要么一直使用迭代器,要么使用索引,但不要混用。 使用迭代器:

        for(Vector<T>::iterator i=&items[998]; i>=position; i--)
        {
            *(i+1)=*i;
        }

编辑:

[刚刚注意到Scheff在完成此编辑后得出的答案]

上面调用v.insert(v.begin(), value)未定义行为,因为iitems之前迭代。 为了避免这种情况,迭代应该在它从items掉落之前停止:

        for(Vector<T>::iterator i=&items[999]; i > position; i--)
        {
            *i = *(i-1);
        }

另请注意,循环后面的行也应该修复:

        items[*position]= item; // <--- BUG: also mixing indexes and iterators


或者使用索引:

  for(int i= 998; begin() + i>=position; i--) { items[i+1]=items[i]; } 

除了Michael Veksler的答案之外 ,我试图让它工作(因此需要更长时间)。

所以,他的第一个提议修复和另外

items[*position]= item;

变成

*position = item;

以下测试编译并运行:

#include <iostream>

int main()
{
  Vector<double> vec;
  vec.insert(vec.begin(), 1.0);
  vec.insert(vec.begin(), 2.0);
  vec.insert(vec.begin(), 3.0);
  std::cout << "vec.size(): " << vec.size() << '\n';
  for (int i = 0; i < vec.size(); ++i) {
    std::cout << "vec[" << i << "]: " << vec[i] << '\n';
  }
  return 0;
}

输出:

vec.size(): 0

哎呀!

insert()中也缺少used的更新:

++used;

而且,现在它看起来更好:

vec.size(): 3
vec[0]: 3
vec[1]: 2
vec[2]: 1

完整的MCVE

#include <iostream>

template <class T>
class Vector {
    public:
        typedef T* iterator;
        Vector () {  }

        T& operator[](unsigned int i) {
           return items[i];
        }
          // T& operator[](iterator i) {
           //return items[*i];
        //}

        iterator begin () {
            return &items[0];
        }
        iterator end () { 
            return &items[used];
        }
        int size () { return used; }

        iterator insert (iterator position, const T& item) { 

            for(Vector<T>::iterator i=&items[998]; i>=position; i--)
            {
                *(i+1) = *i;
            }
            *position = item;
            ++used;
            return position;
        }
    private:
        T items[1000];
        int used=0;
};

int main()
{
  Vector<double> vec;
  vec.insert(vec.begin(), 1.0);
  vec.insert(vec.begin(), 2.0);
  vec.insert(vec.begin(), 3.0);
  std::cout << "vec.size(): " << vec.size() << '\n';
  for (int i = 0; i < vec.size(); ++i) {
    std::cout << "vec[" << i << "]: " << vec[i] << '\n';
  }
  return 0;
}

在coliru现场演示

因此,您可以将此上下文中的迭代器视为基本上是指向数组中元素的美化指针,正如您在类的开头的typedef中定义的那样。

当您尝试在插入函数中访问数组中的元素时,您实际上是取消引用这些指针以生成元素本身,然后使用这些元素作为数组的索引,从而产生索引错误的错误类型。

例如,假设你有一个Vector<std::string> 在insert函数的for循环中,你有这一行:

items[*(i+1)]=items[*i];

因为i是你定义的iterator ,所以i的类型为std::string * ,因此*i的类型为std::string 当你编写items[*i]你试图使用std::string作为你不能做的数组的索引。

相反,您应该使用类似于以下内容的行:

*(i + 1) = *i

您的代码中也存在一些逻辑错误,但我会让您稍后再找到它们。

希望这可以帮助!

看看如何实现std::move_backward

template< class BidirIt1, class BidirIt2 >
BidirIt2 move_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last)
{
    while (first != last) {
        *(--d_last) = std::move(*(--last));
    }
    return d_last;
}

你不需要移动任何元素过去的end ,我们可以重写你的insert是相似的

iterator insert (iterator position, const T& item) { 
    for(iterator i = end(), d = end() + 1; i != position; )
    {
        *(--d) = std::move(*(--i));
    }

    *position = item;
    ++used;

    return position;
}

请注意,如果您尝试插入完整的Vector ,则这是未定义的

暂无
暂无

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

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