We have different types of initializing class or struct member variable at c++ one of them is:
struct foo {
foo() : a(true), b(true), c(true) {}
bool a;
bool b;
bool c;
} bar;
and another one is :
struct foo {
bool a = true;
bool b = true;
bool c = true;
} bar;
Is there differences between them ?
which one is better to use ?
TL;DR Don't care about such trivialities unless you know you have to. And if you have to, you need to analyze concrete assembly.
In general from pure language perspective such questions do not make sense. For what it's worth, c++ compiler can cripple performance if it wished. Any program exhibiting the same behaviour is just as legal, and performance is not a visible effect.
Talking about performance makes sense only in concrete application that is concrete assembly using a particular compiler and configuration, especially optimizations.
Full study: I will be using clag 7.0.0 on godbolt compiler explorer
Your case is weird because it defines global values.For default optimization options:
So clearly option 2 seems better:
__cxx_global_var_init: # @__cxx_global_var_init
push rbp
mov rbp, rsp
movabs rdi, offset bar
call foo::foo() [base object constructor]
pop rbp
ret
foo::foo() [base object constructor]: # @foo::foo() [base object constructor]
push rbp
mov rbp, rsp
mov qword ptr [rbp - 8], rdi
mov rdi, qword ptr [rbp - 8]
mov byte ptr [rdi], 1
mov byte ptr [rdi + 1], 1
mov byte ptr [rdi + 2], 1
pop rbp
ret
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
push rbp
mov rbp, rsp
call __cxx_global_var_init
pop rbp
ret
bar:
.zero 3
bar2:
.byte 1 # 0x1
.byte 1 # 0x1
.byte 1 # 0x1
However using -O1
reduces code to no difference:
bar:
.byte 1 # 0x1
.byte 1 # 0x1
.byte 1 # 0x1
bar2:
.byte 1 # 0x1
.byte 1 # 0x1
.byte 1 # 0x1
When using foo
as type in a program ctor is generated for both cases -O0
and -O1
(same ctor for each case, different per optimization level). See: https://godbolt.org/z/0il6ou
And for -O2
the objects get dissolved.