【问题标题】:The std::pair in the std::map is returned as conststd::map 中的 std::pair 作为 const 返回
【发布时间】:2017-07-07 10:55:08
【问题描述】:

我的示例代码是

class A
{
    int a = 0;
public:
    void setA(const int value)
    {
        a = value;
    }
};

std::map<std::string, std::set<A>> Map{{"A", {}}};
Map.rbegin()->second.rbegin()->setA(2);

我收到以下错误:“成员函数 'setA' 不可行:'this' 参数的类型为 'const A',但函数未标记为 const”

我的问题是为什么 rbegin() 返回一个指向 A 的 const 指针?或者为什么std:pair的第二个是std::map中的常量?

【问题讨论】:

  • 因为std::map是一个树形结构。在不破坏结构本身的情况下,您无法更改其元素的值。试试std::map&lt;int, int&gt;。 (顺便说一句,std::set 也是如此。)
  • 感谢您的回复。即使,我可能只需要修改该对的第二个(值)?在那种情况下,树的结构不会失效吧?
  • 你可以修改set,但不能通过它的迭代器修改set的内容。您的集合中也没有任何元素(您需要使用额外的 {} 初始化 Map{{"A", {{}}}}
  • 您可以使用 operator[] 更改与键关联的值。
  • 在构建minimal reproducible example 时,您应该已经发现地图是无关紧要的。

标签: c++ c++11 stl


【解决方案1】:

所有std::set 元素都以const 方式暴露。那是因为它们既是键又是值,如果你可以随意修改键,那么你会破坏集合内的树结构。

It is currently not possible to directly modify set elements。您必须删除然后重新插入。

(这与封装图无关。)

【讨论】:

    【解决方案2】:

    基本上,rbegin() 返回一个反向迭代器,它指向A 类型的对象,该对象以const 方式存储在std::set

    这种行为背后的原因很简单:有必要保护 std::set 不被意外更改存储在其中的元素。

    您应该记住,std::set 将其元素存储在树状数据结构中,以确保快速搜索/插入/删除操作。 std::set 内部元素的可能更改可能导致错误的元素比较和数据结构的损坏,这就是为什么所有迭代器都返回 begin()/end() 方法及其类似物以 const 方式暴露元素.

    【讨论】:

    • en.cppreference.com/w/cpp/container/set/rbegin rbegin 不返回 const 反向迭代器,除非接收者是 const 限定的
    • @xaxxon 据我所知,std::set reverse_iterator 和 const_reverse_iterator 应该是相同的 typedef。
    • 这似乎适用于 c++11 及更高版本:en.cppreference.com/w/cpp/container/set 但不是之前的。
    • @xaxxon 是的,完全正确。
    • @xaxxon 我不喜欢前面的措辞,因为它可能会产生误导。我已经编辑了答案。谢谢你指点我。
    猜你喜欢
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    相关资源
    最近更新 更多