编辑: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));
事实上,这里有两个问题:
查看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实现存在问题。
答案 0 :(得分:2)
看看http://en.cppreference.com/w/cpp/container/set。
它清楚地表明,自C ++ 11以来,std::set
只知道常量迭代器,可能是为了避免无意中修改元素的插入位置。
无论如何,返回类型为const T&
,而不是const T
。
这意味着你可以就地修改元素,如果你向编译者保证你通过强制转换知道你在做什么,但是如果这改变了排序顺序,那么你得到你应得的。