【问题标题】:C++ replacement: Replacing every occurence of v[x] with v.at(x)C++ 替换:用 v.at(x) 替换每次出现的 v[x]
【发布时间】:2021-01-01 03:12:48
【问题描述】:

在 C++ 中,对于向量 v,v.at(x) 的行为类似于 v[x],但如果访问不存在的元素,它会引发越界错误。

我希望始终使用v.at(x),但是写起来不如v[x] 方便。有没有办法让v[x] 表现得像v.at(x),也许使用类似#define 的东西?

如果没有,是否有更好的解决方案来解决总是抛出越界错误?

【问题讨论】:

  • “使用类似#define的东西”应该永远是你最后的手段。您可能必须为此编写一个自定义容器,因为operator[] 不能在类外重载。
  • “[我]有更好的解决越界错误的方法”...?是的,正确验证所有索引。特别是从用户输入派生(或直接来自)的索引。连同代码审查和彻底的单元测试,它应该(理论上)可以解决所有问题。
  • C++ 标准库的一些实现在调试模式下支持边界检查。例如,请参阅 GCC STL bound checkingHow to make std::vector's operator[] compile doing bounds checking in DEBUG but not in RELEASE
  • 我经常使用assert。您可以随意使用它,因为它在发布版本中的运行时开销为零。
  • 使用迭代器(以及 C++11 及更高版本)基于范围的循环,有意识地最小化向量索引的使用,并且 - 如果必须使用索引 - 正确验证索引。你会发现有很多情况下向量索引是可以避免的——稍加思考。

标签: c++ c++11 vector indexoutofboundsexception


【解决方案1】:

你可以考虑在新的继承中重载方法,如下

#include <iostream>
#include <vector>

template< class T, class allocator =  std::allocator<T>>
struct Vector : std::vector<T, allocator>{
    using std::vector<T, allocator>::vector;

    const T& operator[](size_t i)const{
        return this -> at(i);
    }

    T& operator[](size_t i){
        return this -> at(i);
    }
};

template< class T>
Vector(size_t, T ) -> Vector<T>;//if u want to use c++17 deduction guides

int main()
{
    std::vector<int> vec1(4,1);
    std::cout << vec1[4];

    Vector vec2(4,1);
    std::cout << vec2[4];

}

【讨论】:

    【解决方案2】:

    您可以使用带有调用方法 at() 的运算符 [] 的代理对象。当然,这并不是你想要的,但语法是相似的:你必须写 at(v)[x] 而不是 v[x]。

    概念证明:

    #include <iostream>
    #include <vector>
    
    
    template<class T>
    class AtProxy
    {
      public:
        AtProxy(const AtProxy<T>& proxy) : m_obj{proxy.m_obj} {}
        AtProxy(T& obj) : m_obj{obj} {}
        typename T::reference operator [](size_t index)
        {
          return m_obj.at(index);
        }
      private:
        T& m_obj;
    };
    
    
    template<class T>
    AtProxy<T> at(T& v)
    {
      return AtProxy<T>(v);
    }
    
    
    int main()
    {
      try
      {
        std::vector<int> vec = {1,2,3,4,5};
    
        for(size_t i = 0; i < 5; i++)   
        {
          std::cout << i << std::endl;
          at(vec)[i] = at(vec)[i + 1] + 1;
        }   
      }
      catch(std::exception& e)
      {
        std::cout << "exception: " << e.what() << std::endl;
      }
       
      std::cout << "ok" << std::endl;
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 2021-06-14
      • 2019-08-09
      相关资源
      最近更新 更多