【问题标题】:call size() of const map<string,vector<int> > cause error调用 const map<string,vector<int> > 的 size() 导致错误
【发布时间】:2013-12-28 13:07:15
【问题描述】:
  void example(const map<string, vector<int> > & num);

  int main()
  {
      map<string, vector<int> >num;

      num["A"].push_back(1);
      example(num);

      return 0;
  }

  void example(const map<string, vector<int> > & num)
  {
      cout <<  num["A"].size() << endl;
  }

我认为size()并没有改变num的值,但是为什么编译时会出错? 当我在示例函数中删除关键字 const 时就可以了。

【问题讨论】:

  • 这是因为 num["A"] 是对 std::map 的非 const 操作。
  • C++11 中有一个替代方案:stackoverflow.com/a/13902825/893693
  • @bamboon:哦,感谢上帝!而且,显然,你以前告诉过我这件事……

标签: c++ map


【解决方案1】:

问题不在于对size() 的调用。问题是在const 映射上使用operator[]():如果键不存在,则下标运算符将插入键并因此修改映射。为此,std::map&lt;std::string, std::vector&lt;int&gt;&gt; 当然不能是const

如果您只想访问需要直接使用find() 的值:

void example(std::map<std::string, std::vector<int>> const& num) {
    std::map<std::string, std::vector<int>>::const_iterator it(num.find("A"));
    if (it != num.end()) {
        std::cout << it->second.size() << '\n';
    }
    else {
        std::cout << "No key 'A` in the map\n";
    }
}

...或者您可以使用at(),它会在访问非const 映射上不存在的键时引发异常(感谢bambon 指向this 问题):

void example(std::map<std::string, std::vector<int>> const& num) {
    std::cout << num["A"].size() << '\n';
}

【讨论】:

  • 而且,是的,太可怕了。
【解决方案2】:

问题是没有为 std::map 类型的 const 对象定义运算符 []。下面是操作符的声明

T& operator[](const key_type& x);
T& operator[](key_type&& x);

正如您所见,参数列表的右括号后的限定符 const 不存在。但是成员函数 at 是为 const 对象定义的(参见第二个声明)

T& at(const key_type& x);
const T& at(const key_type& x) const;.

所以你必须使用成员函数而不是下标运算符。

【讨论】:

    【解决方案3】:

    函数num 不知道在另一个函数中已经添加了一个键"A",如果没有,num["A"] 会添加它。因此,要使用[],映射操作数不能是const

    总之,这不是size()的错。

    【讨论】:

      【解决方案4】:

      其他人指出了问题所在。你现在可以做的是例如

        void example(const map<string, vector<int> > & num)
        {
            cout <<  num.at("A").size() << endl;
        }
      

      会慢一点。

      【讨论】:

      • 为什么会慢一些?
      • 因为这个函数执行范围检查。见stackoverflow.com/questions/3269809/…
      • std::map::operator[] 还需要更多的逻辑和检查,因为它可能需要构造元素。
      • @ScepticalJule:恐怕你不明白at 如何在地图上工作。地图上没有范围检查的概念:因为这是通过密钥访问,[]at 都必须搜索密钥并根据它的存在或不存在决定做什么。因此,当密钥存在时,它不太可能变慢。在它缺席的情况下......好吧,他们两个做的事情是如此不同,所以慢一点无关紧要。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2022-08-20
      • 2016-11-11
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      相关资源
      最近更新 更多