Lately I have been having difficulties with constructors, and the different attempts from other questions and guides always have some form of segfault waiting for me at runtime (making compiling 80% of my time spent programming).
The following example shows the basic idea on what I am trying to accomplish:
struct Coord3{
float x, y, z;
Coord3() {x=0;y=0;z=0;};///Is this Correct?
};
struct Stat{
int Str,Dex,Int;
Stat(){Str=0;Dex=0;Int=0;};
};
struct Item{
Stat myStats;
Item(){...};
};
class SimpleChar{
public: ///to keep things simple for now
Coord3 pos;
Stat myStats;
int level;
float health;
Item inventory[20];
SimpleChar(){
level=0;
health=100;
}///What happens with 'pos', 'inventory' and 'myStats' in this class's constructor?
};
int main(){
SimpleChar myChar;
if(myChar.inventory[0].get()!=NULL){...}///this caused the most recent SEGFAULT as mentioned below. Why wouldn't this work?
}
With this example I have a bunch of simpler structs (similar to Coord3 and Stat). These structs are at the base level of my "engine", and are used accordingly to make higher level structs, then those are used to make the highest level structs (such as Item being item related information and SimpleChar having generic RPG character statistics, like an inventory and stats). The errors I get are so different according to the situation that it was difficult to keep track them all, but the most interesting one was a SEGFAULT on:
if(itemSet.inventory[a].get()!=NULL); ///Note: this is originally a shared_ptr AND was in a struct known as 'ItemSet', which held all item information
So basically what I ask is:
When are the default constructors invoked?
When the constructors are used, do they also invoke their member's constructors?
What would be the correct way to declare these members both in the classes and main()?
What is the correct way to create the constructor?
EDIT: The code has been spruced up for anyone that is way too obsessed with if the code is "valid by syntax" instead of actually answering the question.
EDIT 2: Since the SEGFAULTs are not created from constructor format then I ask if it is possible to get a SEGFAULT if an instance variable is too large in size? I mainly ask this because recently I have changed a class member to a pointer instead of an object and it worked fine.
when you declear a class like:
class foo{
public:
foo(){} // this is default constructor
};
But if you write:
class foo{};
The compiler will supply a default constructor for you. When you write:
class SimpleChar{
Coord3 pos; // default constructor of Coord3 will be called,
//if you need somrthing else do that in SimpleChar constructor;
Stat myStats; // same
int level;
float health;
Item inventory[20]; // an array will be created that can hold 20 item,
// constructor (default) will be called 20 times
};
Inside main() if you want to initialise an object with default constructor:
className instanceName;
is enough.
When You write:
SimpleChar myChar;
The following constructor is called:
SimpleChar(){
level=0;
health=100;
};
An additional point ; is mandetory after a class or struct definetion, which is absent in struct item{}
And default access specifier of struct is public but in class it is private, Which means you can not create object in main with default constructor.Edit:
"if an instance variable is too large in size" you may get a std::bad_alloc if it is being allocated dynamically in runtime but generally not a segfault. it happens when you access area you do not own.
1: When are the default constructors invoked?
Default constructors are called when:
You create an object without passing parameters
MyClass* myClass = new MyClass(); //<- this is you invoking it.
When you inherit from a class and dont specify a constructor in the initialization list for that base class.
class MyClass: public BaseClass
{
MyClass()
{
}
};
MyClass* myClass = new MyClass(); // <-- this will invoke the default constructor for "MyClass" and "BaseClass".
When you put an object in any stack and dont specify a constructor.
void methodA()
{
MyClass myClass; // <-- this will invoke the default constructor for "MyClass"
}
Same happens if you declare an object as a member of a class in its stack.
class MyClass
{
MyClass()
{
}
DifferentClass m_member;
};
If you dont specify a different constructor for m_member in the initialization list of MyClass, its default constructor will be used.
2: When the constructors are used, do they also invoke their member's
constructors?
As long as they are in the stack and not in the heap, and you dont specify otherwise in the initialization list of the class. Yes.
3: What would be the correct way to declare these members both in the
classes and main()?
It will depend on what you want, if you want to initialize them with its default constructor, you can just declare them as follow:
MyClass myClass; //<- this is fine.
4: What is the correct way to create the constructor?
A good practice is to ALWAYS initialize your members in the initialization list, for example:
struct Stat
{
int Str,Dex,Int;
Stat(): Str(0), Dex(0), Int(0)
{};
};
A simple example of how the default constructor works:
class base
{
int i;
public:
base()
{
i = 10;
cout << "in the constructor" << endl;
}
};
int main()
{
base a;// here is the point of doubt
getch();
}
Related
Why did the creator of C++ decide to use constructor initializer list to initialize base classes? Why didn't he instead choose to use syntax like the second comment line in the following code?
class A{
public:
A() { }
};
class B : A{
public:
B() : A() { } // Why decide to use this one, using constructor initializer, to initialize base class?
B() { A(); } // Why not choose this one? It's easy for me to understand if it was possible.
};
int main(int argc, char *argv[]){
/* do nothing */
}
The advantage of using an initializer list is, that you have a completely initialized object in the body of the constructor.
class A {
public:
A(const int val) : val(val) { }
private:
const int val;
};
class B : A{
public:
B() : A(123) {
// here A and B are already initialized
}
};
So you have a guarantee that all members, even those of the parent, are not in an undefined state.
Edit
In the example of the question it is not necessary to call the base class in the initializer list, this is done automatically. So I slightly modified the example.
I can see a few possible alternatives to the current C++ rule that base classes and data members of a class type are initialised in the mem-initialiser list of the class type's constructor(s). They all come with their set of issues, which I will discuss below.
But first, note that you cannot simply write a derived constructor like this:
struct Derived : Base
{
Derived()
{
Base(42);
}
};
and expect the line Base(42); to call the base class constructor. Everywhere else in C++, such a statement creates a temporary object of type Base initialised with 42. Changing its meaning inside a constructor (or just inside its first line?) would be a syntax nightmare.
Which means that new syntax would need to be introduced for this. In the rest of this answer, I will use a hypothetical construct __super<Base> for this.
Now on to discuss possible approaches which would be closer to your desired syntax, and present their problems.
Variant A
Base classes are initialised in the constructor body, while data members are still initialised in the mem-initialiser list. (This follows the letter of your question the closest).
The would have the immediate problem of stuff executing in different order than it's written. For very good reasons, the rule in C++ is that base class subobjects are initialised before any data members of the derived class. Imagine this use case:
struct Base
{
int m;
Base(int a) : m(a) {}
};
struct Derived
{
int x;
Derived() :
x(42)
{
__super<Base>(x);
}
};
Written like this, you could easily assume x would be initialised first and then Base would be initialised with 42. However, that would not be the case and instead reading x would be undefined.
Variant B
Mem-initialiser lists are removed altogether, base classes are initialised using __super, and data members are simply assigned in the constructor body (pretty much the way Java does it).
This cannot work in C++ because initialisation and assignment are fundamentally different concepts. There are types where the two operations do vastly different things (e.g. references), and types which are not assignable at all (e.g. std::mutex).
How would this approach deal with a situtation like this?
struct Base
{
int m;
Base(int a) : { m = a; }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x); // This one's OK
r = *pd; // PROBLEM
}
};
Consider the line marked // PROBLEM. Either it means what it normally does in C++ (in which case it assigns a double into a "random place" which the uninitialised reference r references), or we change its semantics in constructors (or just in initial parts of a constructor?) to do initialisation instead of assignment. The former gives us a buggy program while the latter introduces totally chaotic syntax and unreadable code.
Variant C
Like B above, but introduce special syntax for initialising a data member in the constructor body (like we did with __super). Something like __init_mem:
struct Base
{
int m;
Base(int a) : { __init_mem(m, a); }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x);
__init_mem(r, *pd);
}
};
Now, the question is, what have we achieved? Previously, we had the mem-initialiser list, a special syntax to initialise bases and members. It had the advantage that it made clear these things happen first, before the constructor body starts. Now, we have a special syntax to initialise bases and members, and we need to force the programmer to put it at the start of the constructor.
Note that Java can get away with not having a mem-initialiser list for several reasons which don't apply to C++:
The syntax for creating an object is always new Type(args) in Java, whereas Type(args) can be used in C++ to construct objects by value.
Java only uses pointers, where initialisation and assignment are equivalent. For many C++ types, there operations are distinct.
Java classes can only have one base class, so using just super is enough. C++ would need to differentiate which base class you're referring to.
B() : A() { }
This will initialize the base class in user defined way.
B() { A(); }
This will NOT initialize the base class in user defined way.
This will create an object inside of constructor i.e B(){}
I think first initialization has better readability compared to the second and you can also deduce class hierarchy.
Using the c++11 standard, I can initialize class members in two ways:
class MyClass
{
private:
int a = 5;
};
or
class MyClass
{
private:
int a;
public:
MyClass()
{
a = 5;
}
};
Is either method superior to the other for any reason, or is it more an individual style choice?
The second example is not initialisation.
So, of the two examples, the first is the best way to initialise class members.
The traditional way to initialise looks like this:
class MyClass
{
private:
int a;
public:
MyClass()
: a(5)
{}
};
Though we now have inline initialisers as in your first example, since C++11.
This page from the Standard C++ Foundation suggests that, all else being equal, you should prefer to use an initializer list. That is:
Prefer
class Foo {
public:
Foo(int bar) : m_bar(bar) { }
private:
int m_bar;
};
over
class Foo {
public:
Foo(int bar) {
m_bar = bar;
}
private:
int m_bar;
};
Their rationale:
Consider the following constructor that initializes member object x_
using an initialization list: Fred::Fred() : x_(whatever) { }. The
most common benefit of doing this is improved performance. For
example, if the expression whatever is the same type as member
variable x_, the result of the whatever expression is constructed
directly inside x_ — the compiler does not make a separate copy of the
object. Even if the types are not the same, the compiler is usually
able to do a better job with initialization lists than with
assignments.
The other (inefficient) way to build constructors is via assignment,
such as: Fred::Fred() { x_ = whatever; }. In this case the expression
whatever causes a separate, temporary object to be created, and this
temporary object is passed into the x_ object’s assignment operator.
Then that temporary object is destructed at the ;. That’s inefficient.
As if that wasn’t bad enough, there’s another source of inefficiency
when using assignment in a constructor: the member object will get
fully constructed by its default constructor, and this might, for
example, allocate some default amount of memory or open some default
file. All this work could be for naught if the whatever expression
and/or assignment operator causes the object to close that file and/or
release that memory (e.g., if the default constructor didn’t allocate
a large enough pool of memory or if it opened the wrong file).
Conclusion: All other things being equal, your code will run faster if
you use initialization lists rather than assignment.
Regarding default initialization (such as Foo(): m_bar(5) { }) I would also go with the initializer list approach (or the C++11 member initialization approach) just for consistency with the above guideline.
I´m trying to instantiate an object which has no default constructor so it can be referenced from any methods inside the class. I declared it in my header file, but the compiler says that the constructor for the class creating it must explicitly initialize the member, and I can´t figure out how to do that.
Really appreciate your answers, thank you in advance!
The snippet:
MyClass.h
include "MyOtherClass.h"
class myClass {
private:
MyOtherClass myObject;
public:
MyClass();
~MyClass();
void myMethod();
}
MyClass.cpp
include "MyClass.h"
MyClass::MyClass() {
MyOtherClass myObject (60);
myObject.doSomething();
}
MyClass::myMethod() {
myObject.doSomething();
}
MyOtherClass.h
class MyOtherClass {
private:
int aNumber;
public:
MyOtherClass (int someNumber);
~MyOtherClass();
void doSomething();
}
MyOtherClass.cpp
include "MyOtherClass.h"
MyOtherClass::MyOtherClass (int someNumber) {
aNumber = someNumber;
}
void MyOtherClass::doSomething () {
std::cout << aNumber;
}
You are almost there. When you create an object in C++, by default it runs the default constructor on all of its objects. You can tell the language which constructor to use by this:
MyClass::MyClass() : myObject(60){
myObject.doSomething();
}
That way it doesn't try to find the default constructor and calls which one you want.
You need to initialize the myObject member in the constructor initialization list:
MyClass::MyClass() : myObject(60) {
myObject.doSomething();
}
Before you enter the body of the constructor all member variables must be initialized. If you don't specify the member in the constructor initialization list the members will be default constructed. As MyOtherClass does not have a default constructor the compiler gives up.
Note that this line:
MyOtherClass myObject (60);
in your constructor is actually creating a local variable that is shadowing your myObject member variable. That is probably not what you intended. Some compilers allow you turn on warnings for that.
There are two errors
Your code MyOtherClass myObject(60); is not initializing the member of the class, but it's instead declaring a local variable named myObject that will hide the member inside the constructor. To initialize a member object that doesn't have a default constructor you should use member initialization lists instead.
You are trying to learn C++ by experimenting with a compiler.
This second error is the most serious error and if not corrected is going to take you to a terribly painful path; the only way to learn C++ is by getting one or two good books and read them cover to cover. Experimenting with C++ doesn't work well.
No matter how smart you are there's no way you can guess correctly with C++, and in a sense being smart is even dangerous (because you may be tempted to skip over something "you understood already"): the reason is that it happens in quite a few places that the correct C++ way is illogical and consequence of historical evolution of the language.
In many places C++ is the way it is because of history and not because it makes sense, and no matter how smart you are there's no way you can deduce history... history must be studied.
MyClass::MyClass(): myObject (60){
myObject.doSomething();
}
Initialization of the data member ends before constructor function body.in the function body you just assign
In a C++ object, when you call a constructor from another constructor or member function (after the object has already been constructed), does the initializer list of the constructor you're calling still get executed?
In C++11 you can have a constructor delegate work to another constructor in the same class, e.g.1:
#include <iostream>
struct SomeType {
int number;
SomeType(int new_number) : number(new_number) {}
SomeType() : SomeType(42) {}
};
int main() {
SomeType a;
std::cout << a.number << std::endl;
}
In this instance it is forbidden to have an initaliser list after this delegation, e.g. changing the previous example to:
SomeType() : SomeType(42), number(0) {}
is an error.
If the question was "given an inheritance relationship does the initaliser list still get called?" the answer is yes, e.g.
#include <iostream>
struct SomeBase {
SomeBase(int) {}
};
struct SomeType : SomeBase {
int number;
SomeType(int new_number=0) : SomeBase(new_number), number(new_number) {}
};
int main() {
SomeType a;
std::cout << a.number << std::endl;
}
This is fine and works exactly how you'd hope.
It's not legal to directly call a constructor from within another constructor and in C++ prior to C++11 there's no constructor delegation allowed either, so something like:
#include <iostream>
struct SomeType {
int number;
SomeType(int new_number) : number(new_number) {}
SomeType() {
SomeType::SomeType(0); // Error!
}
};
int main() {
SomeType a;
std::cout << a.number << std::endl;
}
Is an error and can't be expressed directly.
The following (which I'd guess is what you had in mind when writing the question) example isn't an error however, but doesn't do what you might hope:
#include <iostream>
struct SomeType {
int number;
SomeType(int new_number) : number(new_number) {}
SomeType() {
SomeType(0);
number = 42;
}
};
int main() {
SomeType a;
std::cout << a.number << std::endl;
}
Here the constructor with no parameters constructs an anonymous temporary instance of SomeType. It's a totally separate instance to the one that the constructor was called for initially. This is perfectly legal, but probably not what you meant to do. If you do this there's a risk that you might create infinite recursion if you're not careful and I think it's probably a good indicator of a design problem if you end up doing something like that!
1 Derived from the Wikipedia C++11 article
I assume you are referring to calling a base-class constructor from WITHIN the initialization list of a derived class. Assuming this is the case, then the BASE class constructor is executed first (including its initializer list), and THEN the derived class's initializer list is called.
In case you're wondering - the base class constructor is ALWAYS called prior to the initializer list being executed for a derived class, EVEN if the call to the base class constructor appears explicitly in the middle or end of the derived class's initializater list (as well as if it appears at the beginning). The reason is that the items in the initializer list are executed in the order they appear in the class DECLARATION in the class's header file, not in the order they appear in the initializer list in the constructor definition. And, the base class constructor is never declared in the derived class declaration. C++ requires that the base class constructor is ALWAYS called before the derived class constructor - whether the call to the base class constructor appears explicitly in the derived class's initializer list, or not - and no matter where it appears in the initializer list.
Don't call the constructor explicitly from another method, or another constructor.
Use two-stage initialization instead if you really need in, in which you call an Init() type method after constructing the object.
You cannot call a constructor explicitly, only by object construction either via new or on the stack. There are ways to hack it (e.g. placement new) but don't do that, just use two stage construction & initialisation.
I'm new to C++, and the whole idea of classes - I'm still reading a book to try and learn. The book I'm reading says that when I construct a class, I can assign default values by doing this:
class foo {
public:
foo(char c, int i);
private:
char exampleChar;
int exampleInt;
};
foo::foo(char c, int i):
exampleChar(c),
exampleInt(i)
{}
This code (to me) looks very messy, and doesn't follow rules that I'm used to in other languages. My question is, what's the difference between doing the above, and this (below, which I personally think looks a lot cleaner)?
foo::foo(char c, int i) {
exampleChar = c;
exampleInt = i;
}
Sort of things I'm thinking about are: are there performance/efficiency issues if done on a large scale - or is it exactly the same?
The first way, by doing : exampleChar(c), exampleInt(i) is called an initializer list.
If you do it the second way, the two variables are default constructed first1, then you assign them a value. (When the actual body of the constructor is entered, anything that hasn't been initialized by the initializer list is default constructed.) This is a waste of time because you're just overwriting the values anyway. For small types like int or char this isn't a big deal, but when those member variables are large types that would take lots of cycles to construct, you definitely want to use the initializer list.
The second way won't waste time giving them a default value and then overwriting it - it will set their values directly to that value you give it (or call the right constructor if the member is an object).
You can see what we mean by doing this:
class MyClass {
public:
int _i; // our data
// default constructor
MyClass() : _i(0) { cout << "default constructor"; }
// constructor that takes an int
MyClass(int i) : _i(i) { cout << "int constructor"; }
// assignment operator
void operator=(int i) { _i = i; cout << "assignment operator"; }
};
class OtherClass {
public:
MyClass c;
OtherClass() {
c = 54;
}
};
OtherClass oc;
You'll see that
default constructor
assignment operator
is printed. That's two function calls which, for other classes, could be expensive.
If you change the constructor of OtherClass to
OtherClass() : c(54) { }
You'll see that
int constructor
is printed. Just one call compared to two. This is the most efficient way.
Initializer lists are also a must when you
have types that have no default constructor. You have to call the right constructor in the initializer list.
have a const member that you want to give some value (rather than just have permantently the default value
have a reference member. You must use initializer lists on these.
tl;dr: do it because it's at least as fast but never slower than the other way, and sometimes far faster.
1 For built in types like int and char, they are actually not constructed at all; they just have the value of whatever memory they happen to have had previously.
The difference is that the compiler will always initialize all members (in declaration order) prior to the first user-defined constructor statement. In the case of a char and an int, which are both primitive types, 'initialization' actually means 'no initialization' here. However, if you have a member with a constructor that does some actual work, this constructor will be called upfront - if you do
foo::foo() {
myComplexMember = MyComplexClass(42);
}
the compiler did already invoke the MyComplexClass default constructor before your code got called, which is a waste of resources (and a compiler error if the default ctor is not accessible).
By using an initialization list, you can customize the default initialization and avoid doing things for nothing. Obviously, this is the way to go.
There are things you can do like that that you couldn't otherwise.
If one of the members doesn't have a default constructor. That's the only way you could initiate the member at construction. (same goes to base class)
You can assign a value to a const member.
You can assure a defined state for the class before the constructor function starts running.
If a member is a reference it needs to be initialized in the Initialization List. Because references are immutable and can be initialized only once in the beginning (like const)
Well, this is a typical FAQ question: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
In your case, using char and int there are no differences.
General rule: use initialization list as possibile, there are very few cases when you can prefer assignment, for example for improve readability:
MyClass::MyClass
{
a = b = c = d = e = f = 0;
}
is better than
class MyClass::MyClass : a(0), b(0), c(0), d(0), e(0), f(0) { }
If the members had non-trivial constructors, in the code below first the default constructors would be called, then the assignments would be executed, while in the code above they would be initialized only one time. So yes, there may be a performance issue.
There is also a practical issue: if they are const, references, or don't have default constructors, you can't use the version below.
There is a subtle, but important difference between those two options. What you have at the top is called a member initialization list. When the object is created, the members in this list are initialized to whatever you put in the parenthesis.
When you do assignment in the constructor body, the values are being first initialized, and then assigned. I'll post a short example below.
Example 1: Member initialization
class foo
{
public:
foo(char c, int i);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i):
exampleChar(c),
exampleInt(i),
exampleBar() //Here, a bar is being default constructed
{
}
Example 2: Constructor Assignment
class foo
{
public:
foo(char c, int i, Bar b);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i, Bar b):
//exampleChar(c),
//exampleInt(i),
//exampleBar()
{
exampleChar = c;
exampleInt = i;
exampleBar = someOtherBar; //Here, a bar is being assigned
}
This is where it gets interesting. Note that exampleBar is being assigned. Behind the scenes, a Bar is actually first being default constructed, even though you did not specify that. Furthermore, if your Bar is more complicated then a simple struct, you will need to be sure to implement the assignment operator in order for you to initialize it in this way. Even furthermore, in order to initialize the Bar from another Bar from the member initialization list, you must implement the copy constructor!
Example 3: Copy constructor used in member init
class foo
{
public:
foo(char c, int i, Bar b);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i, Bar b):
//exampleChar(c),
//exampleInt(i),
exampleBar(b) //Here, a bar is being constructed using the copy constructor of Bar
{
exampleChar = c;
exampleInt = i;
}
I would get into the habit of using initialisation lists. They will not suffer from problems when somebody changes a char to some object where the default constructor is called first, and also for const correctness for the const values!
foo::foo(char c, int i):exampleChar(c),exampleInt(i){}
This construct is called a Member Initializer List in C++.
It initializes your member exampleChar to a value c & exampleInt to i.
What is the difference between Initializing And Assignment inside constructor? &
What is the advantage?
There is a difference between Initializing a member using initializer list and assigning it an value inside the constructor body.
When you initialize fields via initializer list the constructors will be called once.
If you use the assignment then the fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.
As you see there is an additional overhead of creation & assignment in the latter, which might be considerable for user defined classes.
For an integer data type(for which you use it) or POD class members there is no practical overhead.