I could not understand that how can be the pointers same when the text size is equal. It seems like firstStringObj::c_str() overwrittes the previous one's pointer.
#include <iostream>
#include <string>
#include <string>
#include <stdio.h>
std::string getConstCharAndModifyItWithANewString( const char* constchar )
{
std::string stringAtStack( constchar );
stringAtStack += "::isModified";
return stringAtStack;
}
int main()
{
const char* firstConstCharPointer = getConstCharAndModifyItWithANewString("Hi!").c_str();
std::string firstStringObj = "Hi+";
printf(" firstConstCharPointer(%s)(%p)\nfirstStringObj(%s)(%p)\n\n", firstConstCharPointer,firstConstCharPointer, firstStringObj.c_str(), firstStringObj.c_str() );
}
OUTPUT:
firstConstCharPointer(Hi+)(0x4593eb8)
firstStringObj(Hi+)(0x4593eb8)
Your function returns a temporary std::string
object. After the firstConstCharPointer
variable is assigned and the expression is complete, that temporary object gets destroyed, freeing its allocated memory block and leaving the variable pointing at freed memory. This is known as a dangling pointer.
firstStringObj
then allocates a new memory block, which happens to be reusing the same memory block that the temp std::string
had previously allocated and freed. So the dangling pointer happens to now be pointing at valid memory again. That is why your printf()
statement is able to display the same memory address and content for both strings.
But this is undefined behavior. The memory block that gets allocated each time is completely up to the string's Allocator
to decide. The second std::string
could just as easily have allocated a completely different memory block, and then the code would be more likely to crash, or at least print garbage, when it tries to dereference the dangling pointer that is still pointing at invalid memory.
In order for your code to work, you need to change firstConstCharPointer
to a std::string
object so the temp std::string
gets copied properly, eg:
#include <iostream>
#include <string>
#include <cstdio>
std::string getConstCharAndModifyItWithANewString( const char* constchar )
{
std::string stringAtStack( constchar );
stringAtStack += "::isModified";
return stringAtStack;
}
int main()
{
const std::string firstConstStringObj = getConstCharAndModifyItWithANewString("Hi!");
std::string secondStringObj = "Hi!";
std::printf(" firstConstStringObj(%s)(%p)\nsecondStringObj(%s)(%p)\n\n", firstConstStringObj.c_str(), firstConstStringObj.c_str(), secondStringObj.c_str(), secondStringObj.c_str());
}
The pointers are the same on your platform because firstConstCharPointer
is a dangling pointer, it points to deallocated memory.
That's because the std::string
returned by getConstCharAndModifyItWithANewString
is destroyed after assignment expression const char* firstConstCharPointer = ...;
.
So when you create a new std::string
object, the compile choose to use the same memory location as the previous std::string
object, and so the pointers are the same.
On my platform for example the pointers are the same, and they're not in Ideone.
You have classic undefined behaviour. printf
tries to derefenrece firstConstCharPointer
because of %s
. firstConstCharPointer
points to data that has been destroyed because the std::string
associated with this pointer's lifetime stops after the assignment:
const char* firstConstCharPointer = getConstCharAndModifyItWithANewString("Hi!").c_str();
// temporary std::string returned from getConstCharAndModifyItWithANewString destroyed, pointer becomes dangling.
As stated in documentation:
The pointer obtained from c_str() may be invalidated by:
- Passing a non-const reference to the string to any standard library function, or
- Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end() and rend().
So you are using invalid pointer, as destructor is a non-const member function and is not listed above.