Call constructor to initialize variables - c++

I have the following class definition in C++ :
class foo {
private:
int a,b,c;
foo(); // constructor
void setup(int x, int y);
void some_function_that_changes_a_b_c();
}
foo::foo() {
a = b = c = 0;
}
void foo::setup(int x, int y) {
foo(); // <-- I use this to make sure a,b,c are initialized
a = x;
b = y; // <-- c is left unchanged!
}
void foo::some_function_that_changes_a_b_c() {
// here's some code that changes variables a,b,c
}
And then I have a code that uses this class:
foo *a = new foo;
a->setup(1,2);
a->some_function_that_changes_a_b_c();
a->setup(5,7); // <-- HERE IS THE PROBLEM
The problem is that on the second call to setup(), it doesnt run the foo() constructor to reset my values or a,b,c , so the c variable stays with the old value it was on the call to some_function_that_changes_a_b_c(), I tested this with the debugger and it seems like on the second call, foo() is addressing a different memory space for the variables.
Is there a way to fix this?

In C++, constructor is only called once when the object is constructed, and not anymore in your class method. In your code
void foo::setup(int x, int y) {
foo(); // ==> this line
}
A temporary foo object will be created, which is independent of the current this object, and therefore the a, b and c fields of this object will be unchanged.
In order to do what you have in mind, create a class method, say foo::reset(), and call it from inside foo::setup().

You should not call your constructor after the object has been created. Put the functionality into a protected reset() function that is called from both your constructor and the setup function.
Background: Your call to foo() in setup does not reinitialize the object, but create a second local object that is never used. In general, you should refrain from explicitly calling constructors unless you absolutely know what you're doing.

foo(); // <-- I use this to make sure a,b,c are initialized
Unfortunately, it doesn't do that. It creates and destroys a temporary object. You can't call a constructor directly; they are only used to initialise objects at the start of their lifetime.
You could reassign your object with a freshly initialised one:
*this = foo();
or you could move the body of the constructor into a reset function, and call that whenever you want to restore the initial state.
My preferred option would be use separate objects rather than trying to reuse a modified one, and to perform all the "setup" when initialising each object:
foo a(1,2);
a.some_function_that_changes_a_b_c();
foo b(5,7); // known to be in a freshly initialised state

What you are attempting to do is two-stage initialization. This is unnecessary and clumsy in C++. You need to realize two things
The constructor is called at the point of object creation
If you have an object to say f.setup(1, 2, 3); on, that means the constructor must have run already.
now:
foo f; // calls foo() with f
f.setup(1, 2, 3); // foo() has arleady been called
as Ying Xiong has pointed out, the foo() line creates a temporary object unrelated to the this you are working with.
Rather than two stage initialization (constructor, then initializer) you can have your constructor take variables and do the initialization
class foo {
private:
int a,b,c;
public:
foo(int x, int y, int z); // constructor
};
foo::foo(int x, int y, int z)
: a(x),
b(y),
c(z)
{ }
and then instead construct with the values you want
foo f(1, 2, 3);
if you need to "reset" the values each time setup is called, then you're best to use a reset function, or similar. Trying to call a constructor on yourself is possible but not very healthy.
void foo::reset() {
a = b = c = 0;
}

Related

How to call parameterized constructor of member object variable in a class' default constructor in C++?

I want to initialize member object variables in the default constructor of the class.
Let's consider the following,
class ABC {
ABC(int A, int B) {
a = A;
b = B;
}
int a;
int b;
};
class Foo {
Foo();
ABC m_obj1;
};
From the above example, I would like to initialize "obj1" in "Foo::Foo()".
One of the restrictions I have is that I cannot do so in the initializer list, as I need to do some computation before I could initialize the member. So the option available (ASFAIK) is to do so in the body of the default constructor only.
Any inputs, how could I do this?
Edit: Restricting to C++11
Would this be a correct way,
Foo:Foo() {
int x = 10;
int y = 100;
m_Obj1(x, y); //Is this correct? <--------
}
Depending on your exact problem and requirements, multiple solutions might be available:
Option 1: Use a function to do the computations and call Foo constructor
Foo makeFoo()
{
// Computations here that initialize A and B for obj1 constructor
return Foo(A, B)
}
Option 2: Call a function that does the computations and initialize obj1 in Foo member initializer list
ABC initABC() {
// Some computations
return ABC(A, B)
}
Foo() : obj1(initABC()) {}
Option 3: Dynamically allocate obj1, for instance with a std::unique_ptr
Option 4: Use std::optional or an emulated c++11 version as shown by other answers
You simply call the base constructor inside the initializer list of the derived constructor. The initializer list starts with ":" after the parameters of the constructor. See example code!
There is no problem to call functions inside the initializer list itself.
int CallFunc1(int x) { return x*2; }
int CallFunc2(int y) { return y*4; }
class ABC {
public:
ABC(int A, int B):a{CallFunc1(A)},b{CallFunc2(B)} {
std::cout << "Constructor with " << a << " " << b << " called" << std::endl;
}
private:
int a;
int b;
};
class Foo {
public:
Foo(): obj1(1,2){}
Foo( int a, int b): obj1(a, b){}
private:
ABC obj1;
};
int main()
{
Foo foo;
Foo fooo( 9,10);
}
edit:
The best method I can think of for your case is a copy constructor, being more specific on what you need to store helps a lot since if it is just two ints inside a class dynamic allocation is not worth it, the size of the object being constructed makes a difference to what method is best, copy constructors can be slower with much larger data types as the object has to be created twice: once when it is automatically constructed in the parent objects constructor and again when a temporary object is created and all the values have to be copied, which can be slower then dynamically allocating if the size is larger.
As far as I'm aware all objects in a class are automatically initialized/allocated in the constructor so sadly dynamic memory use may be your best bet here.
If you are fine with having the object initialized but empty so you know it is not 'ready' yet you can later fill it with useful data when you would have wanted to initialize it. This can be done with default constructors that set the things inside the object to null values or something similar so you know the object hasn't been properly initialized yet. Then before using the object you can check whether it has been initialized by checking for the null values or by having put a bool in the object that tells you whether it is initialized. Dynamically allocated would still be better in my opinion and makes the code look cleaner overall as all you need to store is a null pointer until the object is needed and then allocated and set to the pointer. It is also very easy to check if the pointer is equal to nullptr to know the state of your object.
Dynamically allocating memory may be a hassle since you have to make sure to get rid of memory leaks and it is slightly slower than using the stack, but it is a necessary skill for c++ since the stack is not enough when making programs that use more than the few available megabytes of data on the stack so if you are doing this simply to avoid the hassle I recommend learning it properly. It would be nice if you could be more specific about what kind of object you want to do this with or if you just want an answer that works for most cases.
eg:
*ABC obj1 = nullptr;
...object is needed
obj1 = new(ABC(constructor stuff));
...obj1 isn't needed
delete obj1;
or c++ automatically deletes it when the program closes.

error: 'new' cannot appear in a constant-expression

class A
{
int data;
public:
void display()
{
cout<<"Value is "<<data;
}
void set_data(int x)
{
this->data = x;
}
A object = new A();
};
When I run the above code, I get the error stating "new cannot appear in constant expression". Why is it so?
Operator new returns a pointer but A is not a pointer type. You want A*:
A* object = new A();
You also want to move the above statement outside your class body and place it into appropriate function such as main():
int main() {
A* p = new A();
// do work
delete p;
}
That being said you either don't need a pointer at all and you can simply use an object with automatic storage duration:
A object;
Or you want to consider using a smart pointer such as std::unique_ptr:
std::unique_ptr<A> p = std::make_unique<A>();
class A
{
public:
A * object = new A(); // In any case not: "A object = new A();"
};
Or:
class A
{
public:
A object;
};
-
See (let's assume, for a moment, that you don't get the error), in both cases, on the first construction of A object, it creates another A object as a data-member. This A data-member (let's call it object.object ) creates in its turn another A as its data-member (let's call it object.object.object), and so to infinity (or until no more memory). I mean, as a data-member, it can't be either as A* object = new A();, or as A object;
-
I am not sure what was your intention, but if you want to link one A-object to another A-object, the class should be something like that:
class A
{
public:
A * object = nullptr
};
you have to make object of class A into main().
void main(){
A object;
}
First of all, you cannot create an object in the class declaration. Class declaration is like a blue print of the class. It is to say these are the components of my class - variables and member functions. You cannot instantiate anything inside it as no memory is allocated during this stage.
Note that you can instantiate an object inside one of the member function including constructor. These are called during object creation when memory is allocated.
Even if you use this statement inside a constructor you will go into an infinite loop as the constructor calls its constructor and so on until you have memory overflow.
You can declare the object in main like this:
int main() {
A obj = new A();
//other operations
} //Object A is destroyed once you come out of main.
Or dynamically like this
int main() {
A* obj = new A(); //dynamic allocation
//other operations
delete obj; //explicitly destroy
}

C++: Returning an object and assigning it to a function

I am an beginner in C++ and would like to do something like this:
myObj f(){
// do stuff
// return instance of myObj
}
int main(){
// do stuff
myObj mO = f();
}
What would I have to do, to make this work in C++?
My thoughts were, that I would have to implement an assign operator for the myObj stuct/class or to write another constructor that looks like this myObj::myObj(myObj mO){...}, which I use like this myObj = myObj(f());.
Is this correct?
Do I have to do more, to make this work?
Could you maybe provide a working example?
Thanks!
That would almost compile as-is.
//define a class
class myObj {};
// return an instance of the class
myObj f() {
return myObj{};
}
// call with the same main as in the question:
int main(){
// do stuff
myObj mO = f();
}
C++ defines for you a copy constructor, an assignment operator and a move constructor if this can be done trivially; in these cases you should have to do nothing, just return an object instance and the caller will get it.
If the object has however some parts that cannot be copied (for example references) then you need to provide copy constructors and assignment yourself (but may be the class indeed shouldn't be copied or assigned).
There are also other limitations that prevent automatic synthesis of the move constructor (to avoid bugs).
Note also that there are cases in which the C++ compiler will synthesize copy constructor and assignment, but using wrong code. You need to be careful (for example if the class contains naked owning pointers).
For a simple case in which everything works out of the box with no need to do anything consider:
// A bi-dimensional point
struct P2d {
double x, y;
};
// Computes the middle point given two points
P2d average(P2d a, P2d b) {
return P2d{(a.x+b.x)/2, (a.y+b.y)/2};
}
As you see nothing is needed in the class to support returning P2d values or accepting P2d parameters.
The compiler in that case automatically completes the definition code to something like:
struct P2d {
double x, y;
P2d(const P2d& other)
: x(other.x), y(other.y)
{
}
P2d& operator=(const P2d& other) {
x = other.x;
y = other.y;
return *this;
}
~P2d() {
}
};

placement new to defer to a different constructor

Is this safe? I'm not using any virtual functions in my actual implementation, but I'm tempted to believe that even if I was, it would still be safe.
class Foo
{
Foo()
{
// initialize things
}
Foo( int )
{
new ( this ) Foo();
}
}
By the time you enter the open curly brace of the Foo(int) constructor, all class members have had their constructor called. If you then force a call to another constructor with placement new, you're overwriting the current state of the class. This basically means all members have their constructors called twice - if something does new in its constructor, you leak that content, and you will really, really mess things up! You're effectively constructing two objects, and the destructors for the members of the first object are never called, since the second object overwrites the memory of the first object.
In other words it's BAD! Don't do it!!
The most common workaround is to use some kind of initialisation function, and call that from both constructors. This won't let you initialize const members and others that must be in the initializer list, though.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3
One worry I have is if Foo uses multiple inheritance you'll need to cast the this pointer to the most base class first. Othewise if the the this is offset (sometimes happens in multiple inheritance) it'll construct at the wrong address.
You wouldn't be safe if you extended another class and that class had a destructor, for example
class Foo
{
int* a;
public:
Foo():a(new int)
{
}
~Foo(){delete a;}
}
class Bar:public Foo
{
Bar()
{
// initialize things
}
Bar( int )
{
new ( this ) Foo();
}
}
First Bar(int) calls Foo(), then it calls Bar() which also calls Foo(). The second time Foo() is called, it overwrites the pointer set up by the first call to Foo(), and the allocated memory is leaked.
The key problem here is that constructors are special - when you write a construct that calls a constructor (for example use new keyword to create an object) not only the constructor body is executed, instead the whole chain of objects is constructed first.
So when you use placement-new syntax to run another constructor first C++ automagically reruns all the base class object constructors and all the member variables constructors and only then the other constructor body is invoked. Sometimes you'll be okay, but many times you will run into unexpected behavior.
It looks like the best solution to this problem is to just create a different function to do the initialization:
class Foo
{
inline void nullify()
{
// initialize things
}
Foo()
{
nullify();
}
Foo( int )
{
nullify();
}
}
As others said, is a bad idea, and as a possible destructive case: what if you do
class Foo
{
Foo()
{
// initialize things
}
Foo( int bar )
{
new ( this ) Foo(bar);
}
}
welcome no the land of infinite recursion.

DynamicArray throws OutOfBounds exception

I know this may sound strange, but yes, it's 2009 and I need to write small application using BCB5 :)
The problem is that DynamicArray throws OutOfBound exception when trying to expand it from within worker thread.
I have global variable, let's say
DynamicArray<double> X;
In main thread I check the length of array and I get 0, which is OK (length wasn't set)
Application->MessageBox(itoa(X.Length,str , 10), "", MB_OK);
Below is my worker thread class
class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;
protected:
void __fastcall Execute();
public:
__fastcall ArrayModifierThread(bool CreateSuspended);
void setX(DynamicArray<double> &a);
};
So far so good. Next I create new thread:
ArrayModifierThread *t = new ArrayModifierThread(true);
t->setX(X); // Pass reference to my global DynamicArray
t->Resume();
Here the Execute() method gets executed:
void __fastcall ArrayModifierThread::Execute()
{
X.Length = 10;
X[5] = 45.5;
}
What I'd expect is that global array is expanded and 6th element gets value of 45.5.
But closer investigation from within main thread gives Length = 0 and ArrayOfBounds Exception:
Application->MessageBox(itoa(__X.Length,str , 10), "", MB_OK);
Application->MessageBox(itoa(__X[5],str , 10), "", MB_OK);
Could anybody tell me what I've missed?
In your Execute method you're modifying the thread's X field, not the global X variable. Although the setX method receives its argument by reference, the member variable is not a reference. It stores a copy of the DynamicArray value, and changing the Length property ensures that it refers to a unique array.
The setX function receives a reference to the global variable, as you correctly observe in your "answer," but it doesn't keep a reference to it. It instead makes a copy of it when it assigns the object's X field.
Perhaps you intended to declare X as a reference as well:
private:
DynamicArray<double>& X;
That could work. Your setX function wouldn't work anymore since you're not allowed to "re-seat" a reference after it's been initialized. Instead, you'd need to initialize it in the thread's constructor:
ArrayModifierThread(DynamicArray<double>& a): X(a) { ... }
You could also store a pointer to the array instead of a reference:
private:
DynamicArray<double>* X;
public:
void setX(DynamicArray<double>& a) {
X = &a;
}
protected:
void Execute() {
X->Length = 10;
(*X)[5] = 45.5;
}
Something else you need to be aware of is that your code is not thread-safe. (Neither is mine here.) You have multiple threads modifying the same shared resource (the array) without any protection, such as a critical section. That's beyond the scope of this question, though. Search Stack Overflow and the rest of the Web first, and then come back to ask a new question if you need help with that issue.
It will not work as the member X is not a reference. When you call set() you are making a local copy of the object, then Execute() is modifying the local version.
class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;
void __fastcall ArrayModifierThread::Execute()
{
X.Length = 10;
X[5] = 45.5;
}
There are three alternative solutions:
Make the your local member variable X a reference.
Since the reference must be initialized on construction you can not use set() to modify it, so pass the reference to the constructor of your object and save it there.
Make the your local member variable X a pointer.
When using set() take the address of the passed in parameter (note it is a reference so you will get the address of the object it is referencing). This also means that the execute needs to be modified to take into account that X is a pointer.
Do not use a local member variable. Just modify the global directly.
Well, it's not quite clear to me.
I thought because of void setX(DynamicArray &a) the worker thread gets a reference to a global variable.
Could you post sample code how should it be done?
This is how my void setX(DynamicArray &a) looks like:
void ArrayModifierThread::setX(DynamicArray<double> &a)
{
X = a;
}