2

我目前正在学习C++,使用时遇到问题

std::string::reverse_iterator 

反转字符串。尝试运行下面的函数时出现令人讨厌的编译器错误。但是,当我切换到使用时,

std::string::const_reverse_iterator

,代码编译运行成功。为什么会出现这种情况,尤其是当该语言的文档说可以声明和使用反向迭代器时?如果我需要说,在反向循环遍历字符串时从字符串中删除元素,并且想要使用反向迭代器怎么办?一个

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> >&’
4

4 回答 4

4

你有一个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从一对迭代器构造 a,请参阅重载 (6)

std::string reverse(const std::string &str)
{
    return /* std::string */ { str.rbegin(), str.rend() };
}
于 2018-09-27T09:11:05.177 回答
3

整个 const 正确性问题user463035818 在旁边指出。您正在展示一些单一的(对 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;
}

现在你的代码默认是正确的。而且,如果您确实尝试错误地修改输入字符串,希望错误会比不小心选择错误的迭代器类型时更清楚。

于 2018-09-27T09:09:06.453 回答
3

str被传递,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您可以使用原地反转字符串。如果您仍想保留原始方法,您的方法可能如下所示:

std::string reverse(std::string str)
                //  ^ pass by value because we need a copy anyhow 
{
    std::reverse(str.begin(),str.end());    
    return str;
}

但是,这可以一步完成,而不是先复制然后反转,如Caleths answer所示。

于 2018-09-27T09:02:25.197 回答
0

请注意,str您的函数是 const 类型的参数。rbegin() 应该返回一个 const 类型的迭代器。这是合理的。

rbegin() 的声明如下:

      reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

因此,您可以const从函数的参数列表中删除关键字以使其运行或str通过 reverse_iterator 修改。

于 2018-09-27T09:22:58.110 回答