5
struct run_male_walker_struct {
        string male_user_name;
        string show_name;
};
typedef struct run_male_walker_struct run_male_walker_struct_t;

in another function:

run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct));

question, is it illegal? As the string is a class, it's size can't be determined by sizeof().

3
  • 6
    You are wrong. The size of the struct run_male_walker_struct can be determined at compile time by sizeof operator. However, using malloc() will leave your std::string instances unconstructed. Commented Sep 30, 2010 at 5:46
  • 3
    @wilx You are correct - but this should be in an answer, instead of a comment :) Commented Sep 30, 2010 at 5:52
  • 4
    Isn't the phrase "C struct" is little misleading...? Moreover, the quesion seem to be on "C++ struct" :) Commented Sep 30, 2010 at 5:55

8 Answers 8

5

This is illegal, but not for the reasons you're thinking.

The difference between std::malloc()/std::free() and new/delete is that the latter will call constructors/destructors, while the former won't. The expression

void* p = std::malloc(sizeof(run_male_walker_struct))

will return a blob of uninitialized memory on which no constructor is called. You shouldn't touch it with a ten foot pole - except for invoking a constructor on it:

run_male_walker_struct* pw = new(p) run_male_walker_struct;

If you do this, you will have to do the reverse, too:

pw->~run_male_walker_struct();

before you free the memory:

std::free(p);

However, that leaves the question why you want to do that.
The only reason to do this should be when you want to separate memory allocation from construction (like, for example, in a pool allocator). But if you need that, it's best hidden behind some interface. A natural one would be overloading new and delete per class. Also, std::vector does this internally.

Sign up to request clarification or add additional context in comments.

Comments

4

Not really sure what you're asking here... Just to be clear, the struct keyword is a valid C++ designation, that functions nearly identically to class except for the default privacy. So if you're compiling with g++, and including the string library, this is a valid statement.

However, calling with malloc() will just give you the memory, not actually construct the values inside that struct. You could more appropriately instantiate it by calling it's default constructor.

Comments

3

The struct definition itself is fine. It results is a non-POD aggregate. But you should prefer the use of new and delete over malloc and free because these handle construction and destruction properly. If you want to keep using malloc and free you have to use the placement-new to properly construct the object and invoke the destructor manually to destroy it before you free it:

#include <new>
...
run_male_walker_struct *p = (run_male_walker_struct*)
    malloc(sizeof(run_male_walker_struct));
new(p) run_male_walker_struct; // <-- placement-new
...
p->~run_male_walker_struct(); // <-- pseudo destructor call
free(p);

Or simply:

run_male_walker_struct *p = new run_male_walker_struct;
...
delete p;

BTW: the typedef is not necessary in C++

Comments

2

Try not to use malloc, if you are in C++. Using NEW is a better alternative, when you browse into the NEW() code, you will realize it does call malloc!!!

The pros of using NEW is it will call the constructor of your class instantiated.

Another minor comment, the code you provided should not be compilable:

run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct));

Should be

run_male_walker_struct_t *p = (run_male_walker_struct_t*)malloc(sizeof(struct run_male_walker_struct));

this is due to malloc will return a void*.

Comments

1

Using malloc() would work, but using it will only create enough space for your struct. This means that you will not be able to use your strings properly, because they weren't initialised with their constructors.

Note that string classes don't have their contents in stack memory, but in dynamic memory, which doesn't affect the size of the struct. All classes and structs have a static size, that are known at compile-time (if the struct/class was defined).

I would suggest using new. Using malloc will stuff up the strings.

This raises a question of my own, how did constructors get called on dynamically allocated instantiation in C (were there no such things as constructors in C?). If so, yet another reason against using pure C.

2 Comments

C does not have constructors and destructors.
There's no implicit function invocation in C... if you wanted to initialise an object you called the "constructor" for that yourself (which may or may not have embedded the malloc() call). For example, an API might allow p = new_string("initial value");, with implementation determining whether free(p) or delete_string(p) was needed at the other end. Or even worse ala p = (struct string*)malloc(bytes); string_init(p); ... string_done(p); free(p), or the common unencapsulated approach p = ...malloc(). p->size = 0; ......
1

How about

run_male_walker_struct_t * p = new run_male_walker_struct_t:

Comments

1

I'm fairly sure this is legal because the size of the std::string object will be known even if the lengths of the strings are not known. The results may not be what you expect though because malloc won't call constructors.

Try this:

std::string testString1("babab");
std::string testString2("12345678");
std::string testString3;
std::cout <<" sizeof(testString1)" <<sizeof(testString1) << std::endl;
std::cout <<" sizeof(testString2)" <<sizeof(testString2) << std::endl;
std::cout <<" sizeof(testString3)" <<sizeof(testString3) << std::endl;

On my machine this gives me the following output:

 sizeof(testString1)8
 sizeof(testString2)8
 sizeof(testString3)8

Also is there some reason you are not using:

run_male_walker_struct_t *p = new(struct run_male_walker_struct);

This is the correct way to do it in c++, using malloc is almost certainly a mistake.

EDIT: see this page for a more detailed explanation of new vs malloc in c++: http://www.codeproject.com/KB/tips/newandmalloc.aspx

Comments

1

The answer depends on what you mean by a "C struct".

If you mean "a struct that is valid under the C language", then the answer is obviously: it contains a datatype that isn't valid C, and so the struct itself isn't valid either.

If you mean a C++ POD type, then the answer is no, it is not illegal, but the struct is no longer a POD type (because in order to be POD, all its members must be POD as well, and std::string isn't)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.