int main()
{
string s("some string");
if (s.begin() != s.end())
auto it = s.begin();
*it = toupper (*it) ; // Error ; the identifier "it" is undefined
}
为什么*未定义?为什么我们需要在迭代器维度中使用dereference?
答案 0 :(得分: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:迭代器类型的相关性
前向迭代器满足输入迭代器的所有要求,并且只要指定了输入迭代器就可以使用;双向迭代器也满足前向迭代器的所有要求,并且可以在指定前向迭代器时使用;随机访问迭代器也满足双向迭代器的所有要求,并且可以在指定双向迭代器时使用。
<强> =&GT;迭代器提供间接(以比指针更通用的方式)并且需要取消引用以跟随间接,访问其值。
#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;
}