Default constructor for struct with Long and pointer - c++

I am in the process of learning c++.
I have a struct like this:
struct Info {
const Long rate;
A* ptr;
}
I have a constructor which takes all the arguments as its parameters to initialize the struct. However, this struct is part of another class which will be serialized using boost serialization. In order to serialize that class I would need a default constructor for this struct. However, when I try to write a default constructor such as
Info () {
}
I get an error C2758 that the member rate should be initialized in the constructor.
How to get a default constructor for such a struct which I can use to serialize my class.

You need to initialize the constant value, so:
Info () : rate(0) {
}

The error is probably due to the fact that your Long class does not have a default constructor either.
There are two ways of fixing this:
Add a default constructor to Long, or
Add rate to the initialization list of Info's constructor.

You can see the msdn documentation for C2758 for a description of the error.
In basic term's, a const variable must be initialised in all constructors. The compiler enforces that any built in type or pointer member that is const must be initialised when the object is constructed, as you won't get a chance to give it a meaningful value after construction ( if you could change it after it was created, how is it const ? ).
Also, as a general rule of thumb, it is always a good idea to initialise members that don't have a default constructor ( built in types, pointers, and objects without default constructors ) to something, in all your class constructors. Otherwise they will either be initialised to some random value ( primitives or pointers ), or you will get a compile error ( objects without default constructors ).
Info()
: rate(0)
, ptr(nullptr)
{
}
If you are assigning values to some of your parameters from constructor arguments, don't forget to assign a value to the other members as well.
Info( Long rate)
: rate( rate )
, ptr(nullptr)
{
}

try this :
struct Info {
const Long rate;
A* ptr;
Info():rate(0){} // as Matthew guessed, call the correct Long constructor
// or define a default constructor for Long
};

Related

Can't initialize field outside initializer list

I'm having trouble with something that seems very easy, so I must be overlooking something.
I need to construct a class that has a field that is also a class (non-POD). The class of the field has a default constructor and a "real" constructor. The thing is that I really can't construct the field in the initializer list, because in reality the constructor has a parameter that is a vector which needs a somewhat complex for loop to fill.
Here is a minimal example that reproduces the problem.
ConstructorsTest.h:
class SomeProperty {
public:
SomeProperty(int param1); //Ordinary constructor.
SomeProperty(); //Default constructor.
int param1;
};
class ConstructorsTest {
ConstructorsTest();
SomeProperty the_property;
};
ConstructorsTest.cpp:
#include "ConstructorsTest.h"
ConstructorsTest::ConstructorsTest() {
the_property(4);
}
SomeProperty::SomeProperty(int param1) : param1(param1) {}
SomeProperty::SomeProperty() : param1(0) {} //Default constructor, doesn't matter.
But this gives a compile error:
ConstructorsTest.cpp: In constructor 'ConstructorsTest::ConstructorsTest()':
ConstructorsTest.cpp:4:19: error: no match for call to '(SomeProperty) (int)'
the_property(4);
^
It gives no suggestions like it usually would of what functions could have been intended instead.
In the above example I would just initialize the_property in the initializer list, but in reality the 4 is actually a complex vector that needs to be generated first, so I really can't. Moving the_property(4) to the initializer list causes the compilation to succeed.
Other similar threads mention that the object must have a default constructor, or that it can't be const. Both requirements seem to have been met, here.
You can't initialize data member inside the constructor's body. (the_property(4); is just trying to invoke the_property as a functor.) You can only assign them like:
ConstructorsTest::ConstructorsTest() {
the_property = ...;
}
but in reality the 4 is actually a complex vector that needs to be generated first
You can add a member function which generate the necessary data, and use it to initialize the data member in member initializer list. e.g.
class ConstructorsTest {
...
static int generateData();
};
int ConstructorsTest::generateData() {
return ...;
}
ConstructorsTest::ConstructorsTest() : the_property(generateData()) {
}
You cannot initialize a variable twice.1 When your constructor has started, all member subobjects will have been constructed. If you do not provide a member initializer in the constructor, or a default member initializer in the class definition, then it will perform default initialization. Regardless of what form it takes, you can't construct it again.
Complex multi-statement initialization is best done via a lambda function:
ConstructorsTest::ConstructorsTest()
: the_property( []{ /* Do Complex Initialization */}() )
{
}
1: Well... you can, but not like that. And you really shouldn't for cases as simple as this.

Can I call optional::emplace as a member initializer?

I'm trying to add a new constructor an existing class and wondering if I can somehow do an emplace initialization of an optional and then use that value in the initializer for another member value.
For example:
class sample {
my_type sc;
optional<opt_type> run;
sample() :
sc( gen_default() ) {
}
enum ctor_alt { ctor_alt };
sample( ctor_alt ) :
emplace( run, ctor_arg ), /* Possible somehow? */
sc( run.field ) {
}
My primary motivation is that I don't want to alter the type of my_type. There are many users of this variable and putting it in a wrapper would require changing a lot of code.
emplace is a member function, and you cannot execute a member function until you've constructed the object (unless you're the object's constructor). But if you want to construct an engaged optional<T> in-place, you can simply use the std::in_place constructor:
run( std::in_place, ctor_arg )
However, member initializers are always executed in the order in which the members are declared, not the order in the member initializer list (your compiler ought to warn you if you initialize them out of order). So if you want to use an earlier initializer to initialize a later variable, you have to order them correctly in your declarations:
optional<opt_type> run;
my_type sc;
Sure thing, just call the constructor of std::optional with std::in_place_t:
run{std::in_place, ctor_arg}
std::in_place_t is a tag type to disambiguate when you want the type to construct the value in place instead of copying it.
If you want to use the value of the optional for another member variable, you need to make sure that that member variable comes after the optional, because member objects are initialized in the order that they appear.

C++ constructor syntax and zero-initialization

This is a short question about syntax in c++:
class arrayInit {
public:
bool vars[2];
arrayInit() : vars() {} //1
};
class array {
public:
bool vars[2];
array() {} //2
};
What does 1 and 2 do?
Why they don't zero initialize like this: bool vars[2]={};?
What is the purpose of arrayInit() : and array()? and what is it called so I could search for it?
It's from: https://msujaws.wordpress.com/2010/06/16/initializing-an-array-in-c/
What does 1 and 2 do?
Both 1 and 2 define the default constructor for the respective type
Why they don't zero initialize like this: bool vars[2]={};?
They could if they were using a compiler with c++11 support. Also var() will value initialize the array which is same as vars[2] = {} will explicitly initialize all elements to false
What is the purpose of arrayInit() : and array()? and what is it
called so I could search for it?
They are called the default constructors. C++ compiler will create them for you unless you want to do something special in them. If you were mentioning about what is written beyond the : (colon), that expression is called the initializer list
Read more here
What does 1 and 2 do?
Both allow you to override the default initialization for an array.
InitArray is specifically initializing the vars array with no parameters, I believe it will assume 0 as the default parameter.
Array is not specifically initializing the array, so it is falling back to a default initialization case.
Why they don't zero initialize like this: bool vars[2]={};?
You could do this, this is just another option which encapsulates the bool array in a class to allow you to provide other functionality if you wish.
What is the purpose of arrayInit() : and array()?
If you want default functionality, there is no need to encapsulate the array in its own class. Encapsulation allows you to encapsulate a type to provide different functionality from the default, you could go on to add methods for addition, subtraction, or anything you can think up and have it perform the methods in the way that you specify.
and what is it called so I could search for it?
Good question; Encapsulation, class initialization, array initialization.
http://www.cplusplus.com/doc/tutorial/classes/
Both arrayInit() and array() are default constructors. If the default constructor is missing and other constructors are available, you cannot declare an object from that class type without calling the other constructors e.g. you cannot do this arrayInit arr; without the default constructor.
The part : vars() is called the initialization list. You can read more about them in this link: http://en.cppreference.com/w/cpp/language/initializer_list

How to refrain from CS2512 correctly

Please help me with the following problem:
I have the following classes:
class ChemicalElement
{
private:
std::string _name;
void Init(const std::string& name);
public:
ChemicalElement(const std::string& name);
ChemicalElement(const ChemicalElement& ce);
};
class CombinationRule
{
private:
ChemicalElement _ce1;
ChemicalElement _ce2;
void Init(const ChemicalElement& ce1, const ChemicalElement& ce2);
public:
CombinationRule(const ChemicalElement& ce1, const ChemicalElement& ce2);
CombinationRule(const CombinationRule& rule);
};
The implementation is obvious. I intended to initialize the CombinationRule using the Init method to minimize code duplication. Alas, if I do not use "member initialization list" in each constructor the compiler complains with "error C2512: 'ChemicalElement' : no appropriate default constructor available". Is there an elegant way to solve this error instead of using a default constructor or member initialization list?
BTW: if there are any other problems in the classes definition please add it too. Since I'm revisiting C++ I want to be aware of them.
You should implement constructors of CombinationRule as follows so they will use appropriate constructors of ChemicalElement:
CombinationRule::CombinationRule(const ChemicalElement& ce1,
const ChemicalElement& ce2) : _ce1(ce1), _ce2(ce2)
{
...
}
CombinationRule::CombinationRule(const CombinationRule& rule) :
_ce1( rule._ce1 ), _ce2( rule._ce2 )
{
...
}
I think you are required to put a default constructor in any class where you define any other constructors, if you want to use objects of that class in any kind of array or container. The default constructor's implementation can just be an empty/no-op method though.
You shouldn't need to put in a member initialization list (although using a member initialization list can be more efficient in some cases, since that way your member variables are only initialized once, instead of being initialized once via their default constructor, and then written to a second time by your Init() method)
I think you want this
ChemicalElement * ce1;
I say this because I think its trying to run the default constructor on your CombinationRule and in turn needs to get a ChemicalElement for ce1 and ce2 ... but I could be wrong.
Pretty sure Krill's way is the way to specify the constructor of a variable for a specific constructor BUT i said f that and just made it so ce1 doesn't need to be constructed by the compiler :)
In this particular example I would go on with duplication (it's just writing two initializers, nothing to get obsessive about).
But assuming the real story is more complex: use OO facilities to avoid code duplication.
class CombinationRule : public ElementPair ...
or
class Combination { ElementPair twoElements; ...}
Where ElementPair contains two ChemicalElements and a single constructor (with common code), and Combination rule constructors initialize using constructor of ElementPair.
There are other approaches: initializing members with some InvalidChemicalElement instance or using pointers (auto_ptr) with NULL for InvalidChemicalElement.

Initializing in constructors, best practice?

I've been programming in C++ a while and I've used both methods:
class Stuff {
public:
Stuff( int nr ) : n( nr ) { }
private:
int n;
}
Or
class Stuff {
public:
Stuff( int nr ) {
n = nr;
}
private:
int n;
}
Note: This is not the same as this, similar but not the same.
What is considered best practice?
Initializer lists are preferred. See FAQ 10.6
One big advantage to using initializers: If an exception is thrown anywhere within the initializer list, the destructors will be called for those members that had already been initialized -- and only for those members.
When you use the contructor body to initialize the object, it's up to you to handle exceptions properly and unwind the object as appropriate. This is usually much harder to get right.
Use the initializer list when possible. For an int, it doesn't matter much either way, but for a more complex member object, you'd end up with the default constructor of the object being called, followed by an assignment to that object, which is likely to end up being slower.
Plus, you have to do it that way anyway for const members or members which don't have a default constructor.
If possible, use the first version.
The first is initializing using intializer lists, and actually calls the constructors of the members.
The second is assignment. If n was of a type with a default constructor, it the would have already been called, and then you'd be assigning to it. If n didn't have a default constructor, you'd be forced to use the first type. Likewise if n was a reference: int &n.
If there are no constructors of you members that directly take one of the parameters to your constructor, it may be worthwhile to add private static functions that can do the conversion for you.
I generally try to do the initializer list when I can. For one thing, this makes it explicit that you are initializing code in the constructor. const memebers have to be initialized this way.
If you just put code in the constructor's body, it is quite possible someone may decide to come along and move a big chunk of it into a non-constructor "setup" routine later.
It can be taken overboard though. I have a coworker who likes to create classes that have 2 pages of initilizer code, no constructor code, and perhaps 2 pages for the entire rest of the class' code. I find that really tough to read.
I want to add that you don't need to declare the initializer list on the Header (.h). It can be done at the implementation of the constructor (which is very common).
So then:
//Stuff.h
class Stuff {
public:
Stuff( int nr );
private:
int n;
}
//Stuff.cpp
Stuff::Stuff(int nr)
: n(nr)
{
//initalize complex members
}
is legal and imo concentrates the initialization of fields where it matters. Sometimes we need to initialize complex members in the body, so you have your initializer list and the complex initialization all in the .cpp file.
The second option is not initialization but assignment. With types that have user defined default constructors, the second option will call the default constructor and later on call the assignment operator (whether user defined or not) to assign the value.
Some types cannot be default initialized: If you have an attribute without default constructor, hold references (constant or not) or have constant attributes they must be initialized in the initializer list.
Arrays can be value-initialized in the initialization list, but not in the constructor body:
class X {
public:
X() : array() {} // value-initializes the array
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) array[i]=0; }
private:
int array[10];
};
For POD types, you can value-initialize them in the initialization list but not inside the brackets:
class X {
public:
X() : pod() {} // value-initializes
// equivalent to (but easier to read and subtly faster as it avoids the copy):
// X() { pod = {}; }
private:
PODType pod;
};
Finally, some classes offer functionality through the use of constructors that will be more complex (if achievable) after default construction.
class X
{
public:
X() : v(10) {} // construct a vector of 10 default initialized integers
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) v.push_back(0); }
private:
std::vector<int> v;
};
Last, whenever they are in fact equivalent, initialization lists are more idiomatic in C++.