I've got this code:
class MyClass{
public:
string myString;
MyClass(char *aString){
this->myString = std::string(aString);
}
}
int main(){
MyClass example = MyClass("Hi!");
printf("%s\n", example.myString.c_str());
return 0;
}
Testing this with valgrind shows no problems, but I can't understand why I can avoid using new to create the string copy.
After the constructor execution ends shouldn't "this.myString" be lost in the stack?
Shouldn't I ask for that memory? Why?
Edit: I believe I'm getting confused because doing what I would consider "equivalent" in C, would cause errors when tested with valgrind:
typedef struct MyStruct{
char *p;
}MyStruct_t;
void createMyStruct(MyStruct_t *aStruct, char *text){
char str[10];
strcpy(str,text);
aStruct->p = str;
}
int main(){
MyStruct_t example;
createMyStruct(&example, "Hi!");
printf("%s\n", example.p);
return 0;
}
What am I getting wrong?
This is an error:
this.myString = std::string(aString);
It should be this->myString. (I have heard there is a compiler that implements using . on pointers as an extension... uggh)
Anyway, the effects of this line are:
std::string, initialized by passing aString to its constructor. That constructor copies from your char * into memory which the std::string constructor allocates within the temporary object. A std::string object internally contains a pointer to some allocated storage; it doesn't refer to your string literal any more after this step.this->myString::operator=(std::string const &), where the temporary object binds to the const reference. The std::string::operator= function increases the memory allocation in the target string, and copies bytes over from the source string. (It doesn't "share" the allocation or anything).std::string's destructor deletes the pointer to its storage for the string contents).The end result is that the string contents get copied by value into myString , there are no memory leaks. After Step 2, there are briefly two copies in memory of the string contents.
Note that the compiler may optimize all stages of this process, so if you inspect your generated assembly it may look different. But conceptually, this is the defined list of steps.
I guess you might be coming from Java... if so, C++ has automatic allocation for all data types (whereas Java only has it for primitive types). You can go T(args) anywhere you like, and create a temporary T which lives until the end of the full-expression in which it was created.
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