int 有效,但 string::size_type 无效

Posted

技术标签:

【中文标题】int 有效,但 string::size_type 无效【英文标题】:int works but string::size_type doesn't 【发布时间】:2017-11-02 12:52:44 【问题描述】:
    #include <string>
    #include <iostream>

    using namespace std;

    const string& strReverse(const string&);

    int main() 
        cout << strReverse("POT") << endl;
    

    const string& strReverse(const string& s) 
        static string ret;
        ret = "";


        for(string::size_type i = s.length()-1; i >= 0; --i) 
            ret += s[i];
        

        return ret;
    

上面的代码会导致程序在运行时崩溃。但是,如果我将i 的类型更改为int,它就可以工作。

这是为什么呢?我认为使用string::size_type 比使用特定类型(例如int)“更安全”。使用auto 也会导致程序崩溃。

我认为可能string::size_type 中的类型与数组索引不兼容,因此我尝试将索引i 转换为int,但这也不起作用。

【问题讨论】:

也许 size_type 是无符号的,你从无符号中减去 0-1,这是一个巨大的正数,然后你访问了一堆越界内存 避免此问题的最佳方法是使用迭代器而不是索引,尤其是反向迭代器。更好的是,还有 std::reverse。 除了从概念上考虑之外,简单地使用调试器甚至简单地添加一些诊断打印就可以为您回答这个问题。 为什么是ret static?你认为这有什么好处? 所以,另一个似乎坚持学生必须无缘无故做奇怪事情的练习。我很高兴我自学了。 【参考方案1】:

因为string::size_type 是无符号的,所以for 循环的终止条件i &gt;= 0 将永远为真。您的选择:

    使用int;

    继续使用 size_type 但改变你的循环:

    for(string::size_type i = s.length(); i > 0; --i) 
        ret += s[i-1];
    
    

或者我最喜欢的选择:

    使用std::reverse_iterator 并在一行中完成所有操作:

像这样:

std::string ret(s.rbegin(), s.rend());

一些额外的 cmets:

    不要返回对静态字符串的引用。它不是线程安全的。按值返回(即返回std::string,而不是const std::string&amp;)。

    为获得更好的性能,请为字符串预分配所需的容量:ret.reserve(s.size());

【讨论】:

3.使用基于范围的for @Steve 此处不适用,因为循环需要反向运行。 @Slava 不错。我在这里的回答只关注循环。你说得很对。该函数应该返回一个简单的std::string,而不是const std::string&amp;。 (实际上,它不是悬空引用,因为它是对静态的引用,但这也非常非常糟糕。) 是的,它注意到它没有悬空并删除了我的评论。【参考方案2】:

你应该按值传递和返回std::string

std::string strReverse( std::string s)

     for( size_t i = 0; i < s.size() / 2; ++i )
         std::swap( s[i], s[s.size()-i-1] );
     return s;

它会让你的函数更简单,同时更正确。

【讨论】:

以上是关于int 有效,但 string::size_type 无效的主要内容,如果未能解决你的问题,请参考以下文章

int 有效,但 string::size_type 无效

将 int 值添加到数据库给出错误,但字符串值有效

我的二进制搜索有效,但返回错误的索引

确定C字符串是否是C中的有效int

有效地找到不在大小为 40、400 或 4000 的集合中的整数

实现基于整数的幂函数 pow(int, int) 的最有效方法