In C++, when a function is called, a new stack frame is added to the call stack, containing its parameters and local variables (and other things). Does this also happen when an object constructor is called?
If so, does this change when the constructor uses an initialization list? What is the structure of this stack frame? Does it contain the object's member variables (which must be in the heap after the execution of the constructor)?
You don't need to think constructor especially. It's just a kind of function - for example, This C++ code is
class Test
{
private:
int m_a;
public:
Test() : m_a(0) { puts("Test::Test()"); }
explicit Test(int i) : m_a(i) { puts("Test::Test(int)"); }
void f(char c) { puts("Test::f(char)"); }
~Test() { puts("Test::~Test()");
};
int main()
{
Test t1;
Test t2(3);
t1.f('a');
}
almost similar to
struct Test
{
int m_a;
};
void Test__ctor_0(Test *thiz) { thiz->m_a = 0; puts("Test::Test()"); }
void Test__ctor_1(Test *thiz, int i) { thiz->m_a = i; puts("Test::Test(int)"); }
void Test__f(Test *thiz, char c) { puts("Test::f(char)"); }
void Test__dtor_(Test *thiz) { puts("Test::~Test()"); }
int main()
{
struct Test t1;
Test__ctor_0(&t1);
struct Test t2;
Test__ctor_1(&t2, 3);
Test__f(&t1, 'a');
Test__dtor_(&t1);
Test__dtor_(&t2);
}
this C code.
Of course, the stack frame can be created when you call ctor, if it's not inlined or compiler optimizes call not to create stack frame to reduce the decrease of performance.
(In cdecl of x86, this pointer is sent through ecx register, unlike other parameter. So if the constructor don't use any local variables and don't have any additional parameters, stack frame could be not created.)
Construction is handled like any other method call.
If it doesn't get inlined by the optimizer, a stack frame will be created holding an implicit "this" pointer and all passed-in parameters.
Most architectures' ABIs call member functions by putting the this-pointer into a specific register, or by pushing it onto the stack at a particular position. Constructors are a little unusual language-wise, but from the point of view of the ABI they follow this pattern.
In general, the this-pointer is treated as an implicit first argument to the function. For instance, under the normal x86 calling convention, a pointer to the object is at the "bottom" (memory-order-wise) of the stack. The member variables themselves aren't on the stack; that wouldn't make any sense, because the constructor (as with other member functions) might need to write to those variables, and those writes would need to affect the "real" copy of the object. Hence pushing a pointer to them instead.
Object construction involves more than just the execution of constructor body. First off, all the base subobjects and member subobjects are initialized, and only then does the contructor body run. So when a particular constructor is selected for object construction, the subobject constructors run first, and their arguments are given by the original constructor's initializer list. Afterwards, the constructor body runs, more or less like a normal function, with parameters populated from the constructor arguments.
Related
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.
I have an object that has different constructors. Now I want to add another constructor that based on arbitrary data will try to process that data and call the correct constructor.
AFAIK there are two ways to do it:
static function that returns the created object
static *A from_data(/arbitrary data/);
create a private "init" function that is called by constructors
But I am wondering what are the problems and potential pitfalls of using a placement new on this using the desired constructor. So the code would be:
#include <new>
struct A
{
/*different constructors*/
A(int i) {};
A(double d) {};
A(/*large set of data*/)
{
/*large set of data gets processed and depending on the processing a different constructor gets called*/
this->~A(); //deletes current object
if (true) {
new (this) A(1); //reconstructs object calling the correct constructor for the data
} else {
new (this) A(1.0); //reconstructs object calling the correct constructor for the data
}
};
};
int main(int argc, char* argv[])
{
A a;
}
You want a compile time decision (choice of constructor to delegate to) from run-time information (result of processing a data set).
That means that what you directly want, cannot be done.
But you can use your idea of a static member function that returns the created object, except that instead of A* it should return A, or else a smart pointer.
Re the other suggested solution,
” create a private "init" function that is called by cosntructors
… that doesn't solve the stated problem, and it's a generally bad idea.
Re
” what are the problems and potential pitfalls of using a placement new on this
Well, it's not code you can rely on. I believe it's Undefined Behavior because at the point where the object self-destroys it's not completely initialized. If it should turn out that it's technically well defined for the case at hand, it's not code that you would want to rely on. And in a setting with possible maintenance, someone stumbling on this code would have to replace it rather than wasting time trying to prove UB or not. Just Say No™ to the dark corners of the language.
I briefly considered spending some time trying to figure out whether the shown example results in undefined behavior, or not. But I quickly decided that this is irrelevant, a waste of time, and is completely beside the point because the current C++ standard has a perfectly well-defined, clean mechanism to do exactly the same thing, and it would be more productive to focus my answer on that, instead.
I'm referring to delegating constructors, of course:
class A {
public:
A(int n) {
// whatever
}
A(const char *p, double z)
: A( /* some formula that calculates an int value goes here */ )
{
}
};
The current C++ standard specifies a well-defined way for one constructor to delegate the actual job of constructing and initializing an instance of the class by invoking a different constructor.
Note that this doesn't mean that one constructor gets to execute arbitrary code, before deciding to invoke the delegated-to constructor. The delegation must occur as the very first order of business, where you normally see the initialization section of a constructor; where you see things like the superclasses' constructors, if any.
Only after the delegated-to constructor returns, does the delegated-from constructor have an option of running more code of its own, to finish the job.
But this is just a minor inconvenience, easily addressed with just a little bit of coding:
class A {
public:
A(int n) {
// whatever
}
A(const char *p, double z)
: A(figure_out_an_int_value_from_p_and_z(p, z))
{
}
private:
static int figure_out_an_int_value_from_p_and_z(const char *p, double z)
{
int a_very_complicated_value;
// Some complicated code that computes a_very_complicated_value.
return a_very_complicated_value;
}
};
Having a simple class:
class A {
public:
A() {}
void set(int value) { value_ = value; }
private:
int value_;
};
and its global instance:
A a;
Is it OK to call method set on a not yet constructed object a? That can happen when for example a.set(123) is called from a constructor of another global object in another translation unit.
Will the value in the object a set by calling a.set(123) remain when the non-parametric and empty constructor of A is later called for object a?
Is it ok to call method set on a not yet constructed object a?
No. You may not call member functions for an object that has not yet begun construction.
(Since the answer is no, your second question requires no answer.)
If you may need to access this global instance from multiple translation units during dynamic initialization, you can use the Meyers singleton technique:
A& global_a()
{
static A a;
return a;
}
a will be initialized when global_a() is first called. Note that in a multithreaded program you may need to concern yourself with synchronization of the initialization.
When you write
A a;
a is a constructed object now. In case A is a then A default constructor was already been called
If in 1) you mean it's ok to call set in the constructor, then yes, that's fine because it isn't a virtual method. You cannot call a virtual method in the constructor.
As for 2), what you're asking isn't really clear. The constructor is only called once (although there are ways around that sort of thing, but don't do them) and that is when the object is first created. You can't call the constructor on a a second time so the question doesn't really make sense.
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.
I wanted to run 1,000 iterations of a program, so set a counter for 1000 in main. I needed to reinitialize various variables after each iteration, and since the class constructor had all the initializations already written out - I decided to call that after each iteration, with the result of each iteration being stored in a variable in main.
However, when I called the constructor, it had no effect...it took me a while to figure out - but it didn't reinitialize anything!
I created a function exactly like the constructor - so the object would have its own version. When I called that, it reinitialized everything as I expected.
int main()
{
Class MyClass()
int counter = 0;
while ( counter < 1000 )
{ stuff happens }
Class(); // This is how I tried to call the constructor initially.
// After doing some reading here, I tried:
// Class::Class();
// - but that didn't work either
/* Later I used...
MyClass.function_like_my_constructor; // this worked perfectly
*/
}
...Could someone try to explain why what I did was wrong, or didn't work, or was silly or what have you? I mean - mentally, I just figured - crap, I can call this constructor and have all this stuff reinitialized. Are constructors (ideally) ONLY called when an object is created?
Your line Class(); does call the constructor of the class Class, but it calls it in order to create a "temporary object". Since you don't use that temporary object, the line has no useful effect.
Temporary objects (usually) disappear at the end of the expression in which they appear. They're useful for passing as function parameters, or initializing other objects. It's almost never useful to just create one in a statement alone. The language allows it as a valid expression, it's just that for most classes it doesn't do very much.
There is no way in C++ to call a constructor on an object which has already been constructed. The lifecycle of a C++ object is one construction, and one destruction. That's just how it works. If you want to reset an object during its life, you've done the right thing, which is to call a function to reset it. Depending on your class you might not need to write one - the default assignment operator might do exactly what you need. That's when a temporary can come in handy:
Class myObject;
// ... do some stuff to myObject ...
myObject = Class();
This updates myObject with the values from the freshly-constructed temporary. It's not necessarily the most efficient possible code, since it creates a temporary, then copies, then destroys the temporary, rather than just setting the fields to their initial values. But unless your class is huge, it's unlikely that doing all that 1000 times will take a noticeable amount of time.
Another option is just to use a brand new object for each iteration:
int main() {
int counter = 0;
while (counter < 1000) {
Class myObject;
// stuff happens, each iteration has a brand new object
}
}
Note that Class MyClass(); does not define an object of type Class, called MyClass, and construct it with no parameters. It declares a function called MyClass, which takes no parameters and which returns an object of type Class. Presumably in your real code, the constructor has one or more parameters.
What happens in that line reading...
Class ();
Is that you do in fact call the constructor - for a temporary object that is being constructed from scratch, and which is then immediately destructed since you're not doing anything with it. It's very much like casting to Class, which creates a value using a constructor call, except that in this case there's no value to cast so the default constructor is used.
It's possible that the compiler then optimises this temporary away, so there's no constructor at all - I'm not sure whether that's allowed or not.
If you want to re-initialise members, calling the constructor isn't the way to do it. Move all your initialisation code into another method and call that from your constructor, and when you want to re-initialise, instead.
Yes, this not typical usage. Create a function that resets your variables, and call the method whenever you need it.
You fell prey to a common misreading of c++. The new c++0x makes things a bit clearer.
The problem is constructions syntax looks like a function call.
void foo( int i ) { }
class Foo { };
Foo(10); // construct a temporary object of type foo
foo(10); // call function foo
Foo{10}; // construct a temporary object of type foo in c++0x syntax
I think the c++0x syntax is more clear.
You could do what you want with this syntax. But beware it is very advanced and you should not do it.
MyClass.~Class(); // destruct MyClass
new( &MyClass ) Class;
With such requirements, I generally write a clear() (public) method. I call it from constructor, destructor. User code can call it whenever it wants to.
class Foo
{
public:
Foo() { clear(); }
~Foo() { clear(); }
void clear(); // (re)initialize the private members
private:
// private members
};
To answer the question here, the clear() method may be called whenever it is required to re-initialize the class as it was just after the initial construction.