iterator就是iterator,并不是const_iterator。
但为啥不能改,chatgpt分析得很详细。可以对照一下STL源码看它说得对不。
Q:
std::set<>只有const_iterator吗?
A:
是的,std::set 只提供了 const iterators, 不提供 non-const iterators。这是因为在 set 中,元素的位置是基于其值的,任何改变元素的操作都可能导致元素的重新排序,这也是为什么 set 中的元素是 const 的原因。
所以,当你需要在 set 中遍历元素时,你应使用 const_iterator. 大致的代码如下:
std::set<int>::const_iterator it;
for (it = myset.begin(); it != myset.end(); ++it)
{
std::cout << ' ' << *it;
}
这段代码将遍历 set 中的每一个元素,并将它们打印到标准输出。注意,你不能使用这个 iterator 来改变元素的值,因为set中元素是只读的。如果你试图通过 iterator 修改元素的值,编译器将返回错误。
Q:
但是我看MSVC的STL源码中,std::set<>的find()有两种重载格式,一种返回iterator,另一种返回const_iterator。怎么解释呢?
A:
你的观察是准确的。在MSVC的STL实现中,的确有两种重载版本的std::set<>::find,一种返回iterator,而另一种返回const_iterator。
不过这并不表示你可以通过这些iterator修改元素的值。要注意,虽然形式上返回的是iterator,实际上这些iterator是只读的,也就是说,你无法使用它们来修改元素的值。
这实际上是为了支持常量和非常量版本的成员函数。通常来说,对于那些并未修改数据成员的成员函数,我们会提供一个常量版本和一个非常量版本。非常量版本返回非常量迭代器,而常量版本返回常量迭代器。这样使得在需要返回迭代器的情况下,常量版本的成员函数可以被编译器选中。
总的来说,std::set中的iterator其实是const_iterator。即使find方法返回的是iterator类型,你依然无法用返回的迭代器修改集合内的元素。
Q:
返回的是iterator而不是const_iterator,但依然无法修改iterator指向的数据,请问这是怎么做到的?很好奇其实现细节。
A:
这个问题涉及到C++的内部实现细节。在MSVC的STL实现中,std::set中的迭代器是一种被称为_Tree::iterator的类型,其中的_Tree是set的底层数据结构——一个红黑树。在MSVC的STL实现中,红黑树迭代器的操作符*重载返回的是const类型的引用,如下所示:
const _Ty& operator*() const
{ // return designated object
return (_Mynode()->_Myval);
}
这就是为什么尽管find函数返回iterator,但是你不能通过这个迭代器修改指向元素的值的原因。operator*()返回的是一个const引用,你不能通过这个const引用去修改元素的值。尝试这么做的话,编译器会抛出错误。
这个做法很聪明,因为它允许库的设计者通过在底层实现中施加const来保护容器的元素,同时在API级别呈现出非const迭代器,这对许多代码(如算法)是必要的,它们需要以相同的方式处理const和非const迭代器,即使那些迭代器指向的元素不能被修改。
Q:
如果我不通过operator*()来修改元素,而是用operator->()来修改呢?
A:
在大多数情况下,operator*() 和 operator->() 的作用是相似的, 它们都是用于访问被迭代器指向的元素。当你的迭代器是指向类或结构体的指针时,你可能会需要使用 operator->() 去访问这些结构体或类的成员。
但对于 set 的迭代器来说, 使用 operator->() 来修改元素的值也是不允许的。这是因为无论是 operator*() 还是 operator->(),它们返回的都是对集合元素的 const 引用,这意味着你不能用它们来修改元素的值。如果你尝试这样做, 编译器会抛出错误。
为了证明这一点, 你可以看一下 MSVC STL 中对 set iterator 的 _Ref 类型的定义:
typedef const _Ty& _Ref;
typedef const _Ty * _Ptr;
这意味着 operator->() 返回的其实是一个指向 const 值的指针,因此还是不能用来修改元素的值。这就是 MSVC STL 实现中为何只能用 set 的迭代器来读取值,而不能修改值的原因。
【 在 gameplayer 的大作中提到: 】
: 才知道这个...
: 原来set的iterator也是const_iterator,两者是相同的,而只有unordered_set的iter
: ator才可以修改
: ...................
--
修改:z16166 FROM 61.48.130.*
FROM 61.48.130.*