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

时间:2013-12-20 14:52:29

标签: c++ string stl

我有这个简单的代码:

#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

-thats好的,但当result.resize的行被注释掉时,输出为:

""
"1.0"
0

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

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

编译器:mingw32-g ++ 4.7.1

2 个答案:

答案 0 :(得分:5)

你期待什么?

如果没有resize,则字符串中没有新字符的空格。

尝试复制到该空间无论如何肯定会导致“怪异”[read: undefined ]行为。你正在破坏你的记忆。

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

Live demo

警告!在该实时演示中获得正确的输出并不会证明任何事情,因为未定义的行为有时可能“似乎正常”。但是,我有96k代表你可以相信我。 ;)功能

答案 1 :(得分:1)

当你使用陈述

result.resize(s.length());

您使用值为'\ 0'的三个元素创建并初始化(更精确地分配)字符串。如果未使用此语句,则字符串没有相关内容,并且程序的行为未定义。实际上,带有未注释行的代码等效于以下内容:

string s = "1,0";
string result( s.length(), '\0' );

replace_copy(s.begin(), s.end(), result.begin(), ',', '.');

如果要像使用注释语句那样写,那么你应该使用迭代器适配器std::back_insert_iterator例如

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