std::replace_copy 与 std::string 一起使用的奇怪行为

Weird behavior of std::replace_copy used with std::string

本文关键字:std 一起 replace copy string      更新时间:2023-10-16

我有这个简单的代码:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
    string s = "1,0";
    string result;
    //result.resize(s.length());
    replace_copy(s.begin(), s.end(), result.begin(), ',', '.');
    cout << '"' << result         << '"' << endl;
    cout << '"' << result.c_str() << '"' << endl;
    cout << result.length() << endl;
    return 0;
}

此程序的控制台输出result.resize行未注释为:

"1.0""1.0"3

-没关系,但是当注释掉带有result.resize的行时,输出为:

"""1.0"0

-这可能会导致奇怪的错误,因为result != result.c_str() !!!

replace_copy(可能还有类似的模板)的这种行为是否可以被视为标准库中的错误?我找不到任何与此主题相关的内容。谢谢。

编译器: mingw32-g++ 4.7.1

你期待什么?

如果没有 resize ,字符串中没有空间容纳新字符。

无论如何,试图复制到该空间肯定会导致"奇怪"[阅读:未定义]行为。你正在破坏你的记忆。

replace_copy复制到目标范围,这与将新元素插入目标容器不同。范围必须已经存在...

...除非您使用back_inserter,它的功能是一种假范围,实际上在引擎盖下执行插入:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
    string s = "1,0";
    string result;
    //result.resize(s.length());   // Look, ma! No hands!
    replace_copy(
        s.begin(), s.end(),
        std::back_inserter<std::string>(result),
        ',', '.'
    );
    cout << '"' << result         << '"' << endl;
    cout << '"' << result.c_str() << '"' << endl;
    cout << result.length() << endl;
}
// "1.0"
// "1.0"
// 3

现场演示

警告!在现场演示中获得正确的输出并不能证明任何事情,因为未定义的行为偶尔会"看起来有效"。但是,我有 96k 代表,你可以相信我。;)

当你使用语句时

result.resize(s.length());

您创建并初始化(更准确地说是分配)包含三个值为"\0"的元素的字符串。当不使用此语句时,字符串没有 relements 并且程序的行为是未定义的。实际上,带有未注释行的代码等效于以下内容:

string s = "1,0";
string result( s.length(), '' );
replace_copy(s.begin(), s.end(), result.begin(), ',', '.');

如果要像注释语句一样编写,则应使用迭代器适配器std::back_insert_iterator

例如
replace_copy(s.begin(), s.end(), std::back_inserter( result ), ',', '.');