-11 c++ iterator dereference
int main()
{
string s("some string");
if (s.begin() != s.end())
auto it = s.begin();
*it = toupper (*it) ; // Error ; the identifier "it" is undefined
}
Run Code Online (Sandbox Code Playgroud)
为什么*它未定义?为什么我们需要在迭代器维度中使用dereference?
Pix*_*ist 10
it在if分支的范围内定义.it选择语句后未定义?该标准在第6.4/1节中说明(强调我的):
selection-statement中的子语句(每个子语句,if语句的else形式)隐式定义块作用域(3.3).如果selection-statement中的子语句是单个语句而不是复合语句,则就好像它被重写为包含原始子语句的复合语句一样.
标准中给出的示例与手头的情况相符.
例:
if (x) int i;可以等同地重写为
if (x) { int i; }
现在我们需要通过查看引用的§3.3(再次强调我的)来了解(隐式)块范围如何影响变量的"可见性" :
块(6.3)中声明的名称是该块的本地名称; 它有块范围.其潜在范围从其声明点(3.3.2)开始,到其块结束时结束.在块作用域中声明的变量是局部变量.
=>你去了:你的变量it在一个块中,it结束的范围在块的末尾.因此在该块之后未定义.
迭代器的conecept构建为抽象指针,如第24章中标准中的Iterator库所述.因此,迭代器引用类似指针的引用也引用了一个值.解除引用是访问实际引用值的C++方法.
取消引用指针意味着"给我存储在指针的内存地址的值",而取消引用迭代器意味着"给我存储在该点的值,迭代器逻辑引用".
(注意:指针只是一种特殊的迭代器.)
该标准要求每个迭代器类型定义解除引用操作.
§24.2.1/ 1
所有输入迭代器都支持表达式
*i,从而产生一些对象类型T的值,称为迭代器的值类型.所有输出迭代器都支持表达式*i = o,其中o是某些类型的值,该类型位于可写入特定迭代器类型的类型集中i.
每个迭代器类型都是输入或输出.
§24.2.1/ 2:迭代器的类型
本国际标准根据它们定义的操作定义了五类迭代器:输入迭代器,输出迭代器,前向迭代器,双向迭代器和随机访问迭代器[.]
§24.2.1/ 3:迭代器类型的相关性
前向迭代器满足输入迭代器的所有要求,并且可以在指定输入迭代器时使用; 双向迭代器也满足前向迭代器的所有要求,并且可以在指定前向迭代器时使用; 随机访问迭代器也满足双向迭代器的所有要求,并且可以在指定双向迭代器时使用.
=>迭代器提供间接(以比指针更通用的方式)并且需要被解引用以跟随间接,访问它们的值.
#include <string>
#include <cctype>
int main()
{
std::string s("some string");
if (s.begin() != s.end())
{
auto it = s.begin();
*it = std::toupper(*it);
}
// it not defined here
return 0;
}
Run Code Online (Sandbox Code Playgroud)