Reputation: 769
i have this simple code:
#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;
}
Console output of this program with result.resize
line uncommented is:
"1.0" "1.0" 3
-thats Ok, but when line with result.resize
is commented-out, output is :
"" "1.0" 0
-this can leads into weird errors because result != result.c_str()
!!!
Can this behavior of replace_copy
(and posibly also similar templates) may be considered as error in standard library? I cannot find anything relevant to this subject. Thanks.
Compiler: mingw32-g++ 4.7.1
Upvotes: 0
Views: 565
Reputation: 310930
When you used statement
result.resize(s.length());
you created and initialized (more precisely assigned) the string with three elements with values '\0'. When this statement was not used the string had no relements and the behaviour of the program was undefined.In fact the code with uncommented line is equivalent to the following:
string s = "1,0";
string result( s.length(), '\0' );
replace_copy(s.begin(), s.end(), result.begin(), ',', '.');
If to write as it was with the commented statement then you should use iterator adapter std::back_insert_iterator
For example
replace_copy(s.begin(), s.end(), std::back_inserter( result ), ',', '.');
Upvotes: 1
Reputation: 385098
What did you expect?
Without the resize
, there is no space in your string for the new characters.
Trying to copy into that space regardless will definitely result in "weird" [read: undefined] behaviour. You're mangling your memory.
replace_copy
copies to a target range, which is not the same as inserting new elements into a target container. The range has to already exist…
… unless you use a back_inserter
, which functions as a sort of fake range, that actually performs insertion under the hood:
#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
Warning! Getting the right output in that live demo does not prove anything, as undefined behaviour can occasionally "appear to work". However, I have 96k rep and you can trust me. ;)
Upvotes: 5