【问题标题】:How to get a std::vector that supports negative indices?如何获得支持负索引的 std::vector?
【发布时间】:2016-07-14 19:05:23
【问题描述】:

我有一个向量。我想要做的是在向量的第一个索引处存储一个值。但是,这个值是针对错误的,所以我想引用这个值,比如vector_ [-1]。我该怎么做?

我想出了一个解决方案。 我正在做的是创建一个新向量并将新向量分配给这个向量。

vector_.resize(required_size+1);
vector_ = std::vector<T> (vector_.begin()+1,vector_.end());

此时我可以合法使用vector_[-1]吗?如果没有,请帮助我解决其他问题。

编辑 我找到了解决方法。虽然它不是带有负索引的向量,但我使用的是指向向量第二个成员的指针,所以当我执行ptr[-1] 时,它指向向量的第一个元素。

【问题讨论】:

  • 不,这是错误的。也许将它存储在其他地方?
  • 无法用负索引索引未更改的std::vector。您需要创建自己的课程,可能在内部使用std::vector
  • 向量的索引本质上是一个内存偏移量。所以 -1 是无效的。在我看来,您的索引具有特殊含义,更像是键。也许 std::map 更适合您尝试做的事情。
  • vector_[-1] 实际上是指vector[std::numeric_limits&lt;std::vector::size_type&gt;::max()],因为std::vector::size_type 是无符号的。您将永远无法在 std::vector 中获得负索引
  • 你不能改变 vector 在内部的作用。这就是内部的意思。最好的办法是创建自己的类,该类在内部将索引转换为向量所期望的。

标签: c++ vector indexing stl c++-standard-library


【解决方案1】:

这里是向量的基本起点,您可以在其中指定(有符号的)下标和上标

#include <vector>
#include <cassert>
#include <iostream>
#include <iomanip>


template<class T>
struct any_index_vector
{
    any_index_vector(int min, int max)
    : _zero_index(min)
    , _storage((max - min))
    {
        // assert min - max
    }

    T& operator[](int index)
    {
        assert(index >= lower_limit());
        assert(index <= upper_limit());
        return _storage[index - _zero_index];
    }

    T& operator[](int index) const
    {
        assert(index >= lower_limit());
        assert(index <= upper_limit());
        return _storage[index - _zero_index];
    }

    int upper_limit() const {
        return _zero_index + int(_storage.size());
    }

    int lower_limit() const {
        return _zero_index;
    }

    int extent() const {
        return upper_limit() - lower_limit();
    }

    int _zero_index = 0;
    std::vector<T> _storage {};
};

int main()
{
    any_index_vector<int> v(-1, 9);
    for (int i = -1 ; i < 10 ; ++i) {
        v[i] = (i+6);
    }

    for (int i = -1 ; i < 10 ; ++i) {
        std::cout << "position: " << std::setw(2) << i << " : " << v[i] << std::endl;
    }
}

预期输出:

position: -1 : 5
position:  0 : 6
position:  1 : 7
position:  2 : 8
position:  3 : 9
position:  4 : 10
position:  5 : 11
position:  6 : 12
position:  7 : 13
position:  8 : 14
position:  9 : 15

【讨论】:

  • 你能让这个答案简单且适合初学者吗?我不遵守代码
  • @Rakshith,您可以将整个程序复制粘贴到您的 IDE 中并单步执行。
  • @Rakshith 就这么简单。您可以查找术语限制和范围的字典定义,它们按通常的含义使用。
【解决方案2】:

中不能有负索引,当然,除非提供自己的衰减向量类。

例如检查ref:

原型:reference operator[] (size_type n);

参数:n 位置 容器中的一个元素。请注意,第一个元素有一个 位置为 0(不是 1)。成员类型 size_type 是无符号整数 输入。

这是一个可以做你想做的事的课程:

// Example program
#include <iostream>
#include <string>
#include <vector>

class myVector {
public:
  int get(int index) { return v[index + 1]; }
  void push_back(int value) { v.push_back(value); }
  void print() {
      for(unsigned int i = 0; i < v.size(); ++i)
        std::cout << v[i] << " ";
      std::cout << "\n";
  }
  const int& operator[](int index) const { return v[index + 1]; }
private:
  std::vector<int> v;
};

int main() {
  myVector v;
  v.push_back(404); // error code
  v.push_back(32);  // real data
  v.print();
  std::cout << v[-1] << std::endl;
  std::cout << v.get(-1) << std::endl;
  return 0;
}

输出(Live Demo):

404 32 
404
404

由于您是 C++ 新手,因此运算符重载可能会让您感到困惑,暂时跳过它,稍后再回来阅读 Operator overloading

【讨论】:

  • 谢谢@gsamaras。没想到回复这么快!
  • @Rakshith 除非它不起作用:它不是std::vector 的双向随机访问容器。设计容器类并不完全是初学者的工作,诸如此类的答案使事情变得琐碎到无用的地步。目前所有其他答案都受到这个问题的影响:(
  • std::vector继承myVector有用吗?然后std::vector 的所有功能都可以重复使用,只需要更改需要的部分。
  • @ilya1725 只要您私下std::vector继承,并通过using在公共部分明确公开您需要的功能。一旦重新实现其索引,myVector 就不再是 std::vector。不要破坏LSP
【解决方案3】:

我不明白你为什么要这样做。您也可以将额外值存储在第一个元素中并通过vector_[0] 访问它。但是,如果您坚持使用 -1 作为索引,那么我只看到一种正确的方法:

template<typename T>
class {
public:  
    T& operator[](int index){
        if (index==-1) { return value; }
        else { return vector[index]; }
    }
private:
    T value;
    std::vector<T> vector;
}

但是,我强烈建议不要开始这样的事情。您将浪费大量代码只是为了获得类似于矢量的东西,而您可以简单地使用普通的std::vector 而忘记 -1 索引。

【讨论】:

  • 当然。想想你必须包装的所有其他东西才能获得非功能......
猜你喜欢
  • 2013-02-17
  • 1970-01-01
  • 2021-01-06
  • 2017-10-13
  • 2017-05-10
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
相关资源
最近更新 更多