使用 reverse_iterator 而不是 const_reverse_iterator 并得到讨厌的编译器警告和错误
Using reverse_iterator instead of const_reverse_iterator and getting nasty compiler warnings and errors
我目前正在学习 C++,在使用时遇到问题
std::string::reverse_iterator
反转字符串。尝试 运行 下面的函数时出现严重的编译器错误。但是,当我切换到使用时,
std::string::const_reverse_iterator
,代码编译成功并 运行s。为什么会这样,特别是当该语言的文档说可以声明和使用反向迭代器时?如果我需要说,在反向循环时从字符串中删除元素,并且想使用反向迭代器怎么办? A
const_reverse_iterator
在这种情况下肯定是不够的。任何帮助将非常感激。 :)
std::string reverse(const std::string &str)
{
std::string::reverse_iterator r_iter;
std::string result;
for (r_iter = str.rbegin(); r_iter < str.rend(); r_iter++) {
result += (*r_iter);
}
return result;
}
其中一些错误是:
/usr/include/c++/7/bits/stl_iterator.h: In instantiation of ‘std::reverse_iterator<_Iterator>::reverse_iterator(const std::reverse_iterator<_Iter>&) [with _Iter = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; _Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >]’:
chap6.cpp:40:34: required from here
/usr/include/c++/7/bits/stl_iterator.h:148:22: error: no matching function for call to ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >::__normal_iterator(std::reverse_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >::iterator_type)’
: current(__x.base()) { }
和
/usr/include/c++/7/bits/stl_iterator.h:775:26: note: candidate expects 0 arguments, 1 provided
/usr/include/c++/7/bits/stl_iterator.h:760:11: note: candidate: constexpr __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >::__normal_iterator(const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&)
class __normal_iterator
^~~~~~~~~~~~~~~~~
/usr/include/c++/7/bits/stl_iterator.h:760:11: note: no known conversion for argument 1 from ‘std::reverse_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >::iterator_type {aka __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >}’ to ‘const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&’
str
作为 const&
传递,所以你不能从中删除元素,你也不能得到一个非 const 迭代器,如果你想修改它,你需要删除 const :
std::string reverse(std::string &str)
// ^---------------------- no const if you want to modify it !!!
{
std::string::reverse_iterator r_iter;
std::string result;
for (r_iter = str.rbegin(); r_iter < str.rend(); r_iter++) {
result += (*r_iter);
}
return result;
}
这是常量正确性的问题。您不能将非 const 迭代器获取到常量字符串,因为这将允许您修改实际上是 const 的字符串的元素。
另请注意,还有std::reverse
that you can use to reverse a string in place。如果您仍想保留原始方法,您的方法可能如下所示:
std::string reverse(std::string str)
// ^ pass by value because we need a copy anyhow
{
std::reverse(str.begin(),str.end());
return str;
}
但是,可以一步完成,而不是先复制然后反转,如。
整个 const 正确性问题 放在一边。您表现出了一些不合常理的(对 C++)代码编写习惯。
首先,不要在需要之前定义r_iter
,而是将其限制在循环范围内。除此之外,在这种情况下您真的不关心迭代器的确切类型。您只需要成员函数中的正确的迭代器类型。
所以只需使用 auto
作为迭代器的类型。
std::string reverse(const std::string &str)
{
std::string result;
for (auto r_iter = str.rbegin(); r_iter < str.rend(); r_iter++) {
result += (*r_iter);
}
return result;
}
现在您的代码在默认情况下是正确的。如果您 尝试错误地修改输入字符串,希望错误会比无意中选择错误的迭代器类型时更清楚。
你有一个const std::string
,这意味着你只能对它做const
件事。 std::string::rbegin()
有两个重载:
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
第一个不可用,但第二个不可用。
std::string reverse(const std::string &str)
{
std::string result;
for (auto r_iter = str.rbegin(); r_iter != str.rend(); r_iter++) {
result += *r_iter;
}
return result;
}
请注意,您甚至不需要循环,因为您可以从一对迭代器构造一个 std::string
,请参阅 overload (6)
std::string reverse(const std::string &str)
{
return /* std::string */ { str.rbegin(), str.rend() };
}
请注意,您的函数的 str
是一个 const 类型的参数。 rbegin() 应该 return 一个常量类型的迭代器。这是合理的。
rbegin()的声明如下:
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
因此您可以从函数的参数列表中删除 const
关键字使其成为 运行 或通过 reverse_iterator.
修改 str
我目前正在学习 C++,在使用时遇到问题
std::string::reverse_iterator
反转字符串。尝试 运行 下面的函数时出现严重的编译器错误。但是,当我切换到使用时,
std::string::const_reverse_iterator
,代码编译成功并 运行s。为什么会这样,特别是当该语言的文档说可以声明和使用反向迭代器时?如果我需要说,在反向循环时从字符串中删除元素,并且想使用反向迭代器怎么办? A
const_reverse_iterator
在这种情况下肯定是不够的。任何帮助将非常感激。 :)
std::string reverse(const std::string &str)
{
std::string::reverse_iterator r_iter;
std::string result;
for (r_iter = str.rbegin(); r_iter < str.rend(); r_iter++) {
result += (*r_iter);
}
return result;
}
其中一些错误是:
/usr/include/c++/7/bits/stl_iterator.h: In instantiation of ‘std::reverse_iterator<_Iterator>::reverse_iterator(const std::reverse_iterator<_Iter>&) [with _Iter = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; _Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >]’:
chap6.cpp:40:34: required from here
/usr/include/c++/7/bits/stl_iterator.h:148:22: error: no matching function for call to ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >::__normal_iterator(std::reverse_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >::iterator_type)’
: current(__x.base()) { }
和
/usr/include/c++/7/bits/stl_iterator.h:775:26: note: candidate expects 0 arguments, 1 provided
/usr/include/c++/7/bits/stl_iterator.h:760:11: note: candidate: constexpr __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >::__normal_iterator(const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&)
class __normal_iterator
^~~~~~~~~~~~~~~~~
/usr/include/c++/7/bits/stl_iterator.h:760:11: note: no known conversion for argument 1 from ‘std::reverse_iterator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >::iterator_type {aka __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >}’ to ‘const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&’
str
作为 const&
传递,所以你不能从中删除元素,你也不能得到一个非 const 迭代器,如果你想修改它,你需要删除 const :
std::string reverse(std::string &str)
// ^---------------------- no const if you want to modify it !!!
{
std::string::reverse_iterator r_iter;
std::string result;
for (r_iter = str.rbegin(); r_iter < str.rend(); r_iter++) {
result += (*r_iter);
}
return result;
}
这是常量正确性的问题。您不能将非 const 迭代器获取到常量字符串,因为这将允许您修改实际上是 const 的字符串的元素。
另请注意,还有std::reverse
that you can use to reverse a string in place。如果您仍想保留原始方法,您的方法可能如下所示:
std::string reverse(std::string str)
// ^ pass by value because we need a copy anyhow
{
std::reverse(str.begin(),str.end());
return str;
}
但是,可以一步完成,而不是先复制然后反转,如
整个 const 正确性问题
首先,不要在需要之前定义r_iter
,而是将其限制在循环范围内。除此之外,在这种情况下您真的不关心迭代器的确切类型。您只需要成员函数中的正确的迭代器类型。
所以只需使用 auto
作为迭代器的类型。
std::string reverse(const std::string &str)
{
std::string result;
for (auto r_iter = str.rbegin(); r_iter < str.rend(); r_iter++) {
result += (*r_iter);
}
return result;
}
现在您的代码在默认情况下是正确的。如果您 尝试错误地修改输入字符串,希望错误会比无意中选择错误的迭代器类型时更清楚。
你有一个const std::string
,这意味着你只能对它做const
件事。 std::string::rbegin()
有两个重载:
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
第一个不可用,但第二个不可用。
std::string reverse(const std::string &str)
{
std::string result;
for (auto r_iter = str.rbegin(); r_iter != str.rend(); r_iter++) {
result += *r_iter;
}
return result;
}
请注意,您甚至不需要循环,因为您可以从一对迭代器构造一个 std::string
,请参阅 overload (6)
std::string reverse(const std::string &str)
{
return /* std::string */ { str.rbegin(), str.rend() };
}
请注意,您的函数的 str
是一个 const 类型的参数。 rbegin() 应该 return 一个常量类型的迭代器。这是合理的。
rbegin()的声明如下:
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
因此您可以从函数的参数列表中删除 const
关键字使其成为 运行 或通过 reverse_iterator.
str