In the following code, "situation 1" works as expected on all compilers tested, however "situation 2" it seems to behave differently based on the compiler used.
As an example MSVC has sit1 and sit2 produce the same results, however when using gcc/clang and libstdc++, the modification occurs to the original string and it's copy (sort of like a COW string) even though I'm building using the C++11 switch.
#include <iostream>
#include <string>
int main() {
// situation 1
{
std::string x0 = "12345678";
std::string x1 = x0;
char* ptr = &x0[0] + 3;
(*ptr) = ' ';
std::cout << "1. x0: " << x0 << "\n";
std::cout << "1. x1: " << x1 << "\n";
if ((&x0[0]) == x0.data()) std::cout << "1. ptrs are equal\n";
}
// situation 2
{
std::string x0 = "12345678";
std::string x1 = x0;
char* ptr = const_cast<char*>(x0.data() + 3);
(*ptr) = ' ';
std::cout << "2. x0: " << x0 << "\n";
std::cout << "2. x1: " << x1 << "\n";
if ((&x0[0]) == x0.data()) std::cout << "2. ptrs are equal\n";
}
return 0;
}
GCC (6.1)
1. x0: 123 5678
1. x1: 12345678
1. ptrs are equal
2. x0: 123 5678
2. x1: 123 5678
2. ptrs are equal
MSVC (2015)
1. x0: 123 5678
1. x1: 12345678
1. ptrs are equal
2. x0: 123 5678
2. x1: 12345678
2. ptrs are equal
Is there any reason for the discrepancies in behavior between the various compilers - given that &x0[0] and .data() return the same address?
Situation 2 causes undefined behaviour:
char* ptr = const_cast<char*>(x0.data() + 3);
(*ptr) = 'Z';
According to the specification of std::basic_string::data
(C++14 [string.accessors]/3):
Requires: The program shall not alter any of the values stored in the character array.
In other words, you are not allowed to cast away the const
and modify the string via the pointers returned by data()
or c_str()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With