Say I have the following:
typedef struct {
int x;
int y;
char a;
char b;
} myStruct;
Is it better practice to create a new
It depends on what you treat as initial state. For some people it means all zero, for other people it means a default state, or a meaningful state.
Different defination of initial state you got different way to do it.
For zeroing struct, you just do
struct mystruc s = {0};
If a struct requires specific value initialization, it may looks like:
struct mystruc s = {1, 2, NULL, 0x1234};
For non-trival initialization, I personally like this:
struct mystruc s;
if ( mystruc_init(&s) < 0 ) it_is_fail();
IMO, your second method myStruct s = init();
does not enforce initialization any more than the above methods, programmer may still do myStruct s;
without getting warnings, and I personally hate returning local variable of complicated data type.
If the initialization of your struct cannot fail, I would personally prefer and advise you to just return it by value, since that's what you ultimately want conceptually: have the function deliver some value out of its scope – which is exactly what returning a value is designed for.
It also tends to be the case that if your fingers are used to the "this datatype needs initialization" kind of idiom, then you are less likely to forget
MyStruct foo = init_myStruct();
than performing the 2-step "declare and fill" process. Easier to read, easier to write.
It must also be noted that the pass-in-a-pointer approach can't be used for initializing const
-qualified structs, so there you have essentially no choice but returning by value.
It's basically just convention. The first style is more common in C-code, the second is more common in C++ code.
In C++ they would say that the second is preferred because in the first, if you allocate one of the structs but forget to call init
then you can have a confusing situation with a "headless object" being passed around.
In C++ the init
function would normally just be a constructor, so that there's no possibility of failure to initialize.
In C++ there won't be any difference in efficiency if you turn on optimizations, the compiler will do "copy elision" and optimize the second so that it will look similar to the first.
Personally I often use aggregate initialisation for simple data objects:
struct MyStruct {
int x;
int y;
char a;
char b;
};
int main()
{
MyStruct s = {10, 20, 'e', 'u'};
}
Or hard coded defaults like this:
struct MyStruct {
int x;
int y;
char a;
char b;
};
const MyStruct MyDefault_A = {0, 0, 'a', 'z'};
const MyStruct MyDefault_B = {10, 20, 'e', 'u'};
int main()
{
MyStruct s = MyDefault_A;
}