Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize const member variables

Tags:

I have C++ code that boils down to something like the following:

class Foo{     bool bar;     bool baz;     Foo(const void*); }; Foo::Foo(const void* ptr){     const struct my_struct* s = complex_method(ptr);     bar = calculate_bar(s);     baz = calculate_baz(s); } 

Semantically, the bar and baz member variables should be const, since they should not change after initialization. However, it seems that in order to make them so, I would need to initialize them in an initialization list rather than assign them. To be clear, I understand why I need to do this. The problem is, I can't seem to find any way to convert the code into an initialization list without doing one of the following undesirable things:

  • Call complex_method twice (would be bad for performance)
  • Add the pointer to the Foo class (would make the class size needlessly large)

Is there any way to make the variables const while avoiding these undesirable situations?

like image 770
dooglius Avatar asked Jan 19 '15 17:01

dooglius


People also ask

How do you initialize a const member variable?

To initialize the const value using constructor, we have to use the initialize list. This initializer list is used to initialize the data member of a class. The list of members, that will be initialized, will be present after the constructor after colon. members will be separated using comma.

Do const variables need to be initialized?

A constant variable must be initialized at its declaration. To declare a constant variable in C++, the keyword const is written before the variable's data type. Constant variables can be declared for any data types, such as int , double , char , or string .

Should member variables be const?

const objects are objects you dont want to change, they stay constant during the execution of the program. You can assign a value to them in the member initialization list of the constructor of your class but not beyond that. If you have a variable that can have different values, you should not use const.

Can we initialize constant variable in constructor?

Yes, you can also initialize these values using the constructor.


2 Answers

If you can afford a C++11 compiler, consider delegating constructors:

class Foo {     // ...     bool const bar;     bool const baz;     Foo(void const*);     // ...     Foo(my_struct const* s); // Possibly private };  Foo::Foo(void const* ptr)     : Foo{complex_method(ptr)} { }  // ...  Foo::Foo(my_struct const* s)     : bar{calculate_bar(s)}     , baz{calculate_baz(s)} { } 

As a general advice, be careful declaring your data members as const, because this makes your class impossible to copy-assign and move-assign. If your class is supposed to be used with value semantics, those operations become desirable. If that's not the case, you can disregard this note.

like image 142
Andy Prowl Avatar answered Oct 21 '22 21:10

Andy Prowl


One option is a C++11 delegating constructor, as discussed in other answers. The C++03-compatible method is to use a subobject:

class Foo{     struct subobject {         const bool bar;         const bool baz;         subobject(const struct my_struct* s)             : bar(calculate_bar(s))             , baz(calculate_baz(s))         {}     } subobject;     Foo(const void*); }; Foo::Foo(const void* ptr)     : subobject(complex_method(ptr)) {} 

You can make bar and baz const, or make the subobject const, or both.

If you make only subobject const, then you can calculate complex_method and assign to bar and baz within the constructor of subobject:

class Foo{     const struct subobject {         bool bar;         bool baz;         subobject(const void*);     } subobject;     Foo(const void*); }; Foo::Foo(const void* ptr)     : subobject(ptr) {} Foo::subobject::subobject(const void* ptr){     const struct my_struct* s = complex_method(ptr);     bar = calculate_bar(s);     baz = calculate_baz(s); } 

The reason that you can't mutate const members within a constructor body is that a constructor body is treated just like any other member function body, for consistency. Note that you can move code from a constructor into a member function for refactoring, and the factored-out member function doesn't need any special treatment.

like image 36
ecatmur Avatar answered Oct 21 '22 21:10

ecatmur