Let's say there is a struct
defined as follow:
typedef struct StringBox_t {
string str;
} StringBox;
A newbie may want to use malloc()
to manage the memory like this:
StringBox *strBox = (StringBox *) malloc(sizeof(StringBox));
if (strBox == NULL) {
exit(EXIT_FAILURE);
}
strBox->str = "That's fine."; // Actually it's not!
cout << strBox->str << endl;
free(strBox);
It's problematic because calling malloc()
on a struct
will not call the constructor of its member(s), which is a string
in this case. So strBox->str = "That's fine.";
winds up with a segmentation fault.
Now let's show the right way to handle this.
Using malloc() and free()
Besides calling malloc()
on the struct
, you should do that to every member of the struct
if needed.
#include <string>
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef struct StringBox_t {
string *p_str; // NOTE: we use a pointer here
} StringBox;
int main() {
StringBox *strBox = (StringBox *) malloc(sizeof(StringBox));
if (strBox == NULL) {
exit(EXIT_FAILURE);
}
strBox->p_str = (string *) malloc(sizeof(string));
if (strBox->p_str == NULL) {
exit(EXIT_FAILURE);
}
*(strBox->p_str) = "That's fine finally.";
cout << *(strBox->p_str) << endl;
free(strBox->p_str);
free(strBox);
return 0;
}
Using new and delete
When you use new
on a struct
, the constructors of its members are automatically called. Therefore, you only need to use new
once.
#include <string>
#include <stdlib.h>
#include <iostream>
#include <new> // for std::nothrow
using namespace std;
typedef struct StringBox_t {
string str; // NOTE: we don't use a pointer anymore here
} StringBox;
int main() {
StringBox *strBox = new(nothrow) StringBox;
if (strBox == NULL) {
exit(EXIT_FAILURE);
}
strBox->str = "That's fine too.";
cout << strBox->str << endl;
delete strBox;
return 0;
}
Note that if new
fails, instead of returning a NULL
pointer, an exception is thrown. To handle this, new(std::nothrow)
should be used.
网友评论