Cloud
Cloud

Reputation: 19333

C++ - Efficient approach to initializing structure

A colleague and I were debating the efficiency of certain approaches to zero'ing out a struct. Let's assume we have a simple struct like so:

struct {
  int     iMyInt;
  char    cMyChar;
  double  dCoordinates[128];
} s_t;

My approach would be to do this:

s_t myStruct = { 0 };

My colleague advised this approach instead:

s_t myStruct = { };

He noted that my approach initializes a single element, and then the rest of the elements, in a two-part operation, while his approach initializes the entire struct in a one-part operation that is faster and more efficient.

Is this true, and if so, is it always the case across all compiler optimization levels (ie: does the compiler figure this out and optimize it for me anyways)?

Thank you.

Upvotes: 3

Views: 307

Answers (2)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145249

C++11 §8.5.1/7:

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list

And last dash of C++11 §8.5.4/3:

Otherwise [i.e. T is not a class, not an aggregate, and not a reference], if the initializer list has no elements, the object is value-initialized.

Value-initialized for a simple type like int means zero-initialized.

So the formal effect of {0}, for a type that has 0 value, is the same as the formal effect of {}.

The standard can however not dictate the Quality of Implementation of a compiler. A compiler might react to what it considers bad words in a file name, and just to spite you generate time consuming dummy code before each function call. Likewise it just might, in theory, treat the two notations differently wrt. code generation, even though they mean the same.


Re your colleague’s idea that

He noted that my approach initializes a single element, and then the rest of the elements, in a two-part operation, while his approach initializes the entire struct in a one-part operation that is faster and more efficient.

No, that’s just an incorrect vision of how a compiler might work.

Compilers don’t work that way.

But the empty braces notation has the advantage that it also works with e.g. std::string and any other type T where T() is a valid expression, but T(0) is not.

I.e. it’s slightly more general.


All this said, note that in C++ it’s not necessary to do the C acrobatics

typedef struct Point_tag
{
    int x, y;
} Point;

Instead you can simply do

struct Point
{
    int x, y;
};

Upvotes: 1

Marco A.
Marco A.

Reputation: 43662

First of all the code you posted is invalid: you should declare that structure type as follows

struct s_t {
  int     iMyInt;
  char    cMyChar;
  double  dCoordinates[128];
};

That said: in your specific case the two approaches are the same and everything is zeroe'd out. At -O3 and even -O0 for clang there are no differences for a generic test code which uses any of the above members and/or array elements (at -O0 it even calls memset on the entire structure in both cases).

s_t obj = {0};

movq    %rcx, %rdi
movl    %eax, %esi
callq   memset

s_t obj = {};

movq    %rcx, %rdi
movl    %eax, %esi
callq   memset

Upvotes: 6

Related Questions