use*_*726 3 c++ iterator c++11
我注意到,std::end当涉及到字符串或字符数组时,它总是会引用null终止符.我认为std::end应该引用最后一个有效元素后面的数组的结尾.是'\0'不是有效的元素?它是阵列的一部分.以下是一些都返回true的测试:
#include <iostream>
int main()
{
std::string s("hello!");
auto s_end = *(s.data() + s.size() + 1);
std::cout << std::boolalpha << (*std::end(s) == s_end) << "\n"
<< (s_end == '\0') << "\n";
char buf[6 + 1];
std::copy(s.begin(), s.end(), &buf[0]);
auto buf_end = *(buf + s.size() + 1);
std::cout << (*std::end(buf) == buf_end) << "\n"
<< (buf_end == '\0') << "\n";
char test[3] = {'h', '\0', 'e'};
std::cout << (*std::end(test) == '\0');
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于字符数组,std::end确实指向数组中的最后一个字符.对于
char test[3] = {'h', '\0', 'e'};
Run Code Online (Sandbox Code Playgroud)
指针std::end(test)与test + 3.相同.取消引用它与评估相同test[3].这是未定义的行为.在你的特殊情况下,它恰好发生了它'\0'.但总的来说,它可能产生不同的价值,或崩溃,或完全不同的东西.std::end(test)并没有指向'\0'字符在数组中的索引1 test!
请注意,std::end相对于所有数组,行为均匀.也就是说,如果我们有一个数组T a[N],那么std::end(a)返回a + N,无论T是char什么内容或内容a是什么.它不会给你字符串的结尾; 它为您提供了数组的结尾.同样,返回值始终是a + N.没有例外!
对于std::string,有一个终止空字符,但它不被视为字符串的一部分.(与其他角色不同,在未定义行为的痛苦下,不允许对其进行修改.)如果有的话
std::string s("hello");
Run Code Online (Sandbox Code Playgroud)
然后s[5]将具有null字符的值,但正如我所说,它不被视为字符串的一部分:s被认为有五个字符,而不是六个字符.最好将其std::string视为完全没有空终止.最后一个字符s[4]具有值'o',并且std::end(s)是过去的迭代器std::begin(s) + 4,即std::begin(s) + 5.
这比它看起来更微妙,因为标准在技术上并不能保证std::end(s)可以解除引用,所以你不一定能说它指向终止空值.在实践中,它确实指向终止null,但是取消引用它仍然是未定义的行为.