破坏性地访问设置项目

时间:2014-09-20 12:12:38

标签: c++ set

编辑:C++ STL set update is tedious: I can't change an element in place没有回答我的问题。

map数据类型允许通过引用访问其元素。这允许我们破坏性地修改它们。从描述中可以看出,set数据类型也应该可行。但是,对于集合,它们的迭代器返回集合中元素的副本,而不是引用。迭代器不应该返回引用吗?

最小的工作示例:

struct Test {
  const int id_;

  explicit Test(const int id)
    : id_(id) {}

  bool operator==(const Test & other) const {
    return id_ == other.id_;
  }
  bool operator<(const Test & other) const {
    return id_ < other.id_;
  }
};

int main() {
  std::set<Test> tests;

  tests.insert(Test(10));
  tests.insert(Test(20));

  Test & test = *tests.find(Test(10));

  return 0;
}

gcc 4.9.1回复:

test.cpp: In function 'int main()':
test.cpp:26:37: error: invalid initialization of reference of type 'Test&' from expression of type 'const Test'
   Test & test = *tests.find(Test(10));

事实上,这里有两个问题:

  1. set迭代器返回副本而不是引用。
  2. set迭代器始终是一个const迭代器。
  3. 查看gcc stl的源代码我偶然发现:

    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // DR 103. set::iterator is required to be modifiable,
    // but this allows modification of keys.
    typedef typename _Rep_type::const_iterator iterator;
    typedef typename _Rep_type::const_iterator const_iterator;
    

    这证实了问题2,并让我认为这个stl实现存在问题。

1 个答案:

答案 0 :(得分:2)

看看http://en.cppreference.com/w/cpp/container/set

它清楚地表明,自C ++ 11以来,std::set只知道常量迭代器,可能是为了避免无意中修改元素的插入位置。

无论如何,返回类型为const T&,而不是const T

这意味着你可以就地修改元素,如果你向编译者保证你通过强制转换知道你在做什么,但是如果这改变了排序顺序,那么你得到你应得的。