Reputation: 125
This question is targeted to embedded systems!
I have the following options to initialize an object:
Object* o = new Object(arg);
This puts the object in the heap and returns a pointer to it. I prefer not to use dynamic allocation in embedded software.
Object o = Object(arg);
This creates a new object in the stack and then copies it to object o
and removes it after. This can cause stack overflow if the object is big enough to fit in RAM but not in the stack. I have seen this happening with optimization turned off, I haven't explored if it's different with optimization enabled.
Object o(arg);
This creates the object without making a copy, however how can I "initialize" o
again?
For embedded I prefer the last option since the heap is not used and there's no temporary object in the stack that can do a stack overflow.
However I am puzzled on how I can reinitialize the object again since:
o.Object(arg)
is not allowed.
I could create a method called init(arg) and call
o.init(arg)
that does the same initialization as Object::Object(arg)
but I would prefer not to have to create an extra method with a "non-standard" name I need to remember.
Is there a way to call the constructor of an already created object to reinitialize it again without making a copy?
Upvotes: 3
Views: 3516
Reputation: 56
Consider using placement new on your object's current memory. This will initialize a new object in currently used memory without allocating new memory. That might be a solution for you. For example:
new (&o) Object(args)
Try this:
#include <iostream>
class A
{
public:
A(int i)
{
m_i = i;
}
int m_i;
};
int main()
{
int s = 10;
int *ps = new (&s) int(100);
std::cout << *ps;
std::cout << s;
A a(5);
new (&a) A(49);
std::cout << a.m_i;
}
g++ -std=c++98 main.cpp
returns 10010049, which is correct.
Upvotes: 3
Reputation: 976
Step 1. Get a compiler that works (that is recognizes most obvious opportunities to intialize object in place) and supports at least C++11.
Step 2. For initialization use:
auto o = Object(arg); // won't copy ever with optimization turned on
If you need to reassign with new arguments to the constructor:
o = Object(arg1); // calls move asignment operator
If you need to overwrite the value with value of different object (which you don't plan on using afterwards:
o = std::move(o1); // o1 is the other Object, afterwards o1 is left in 'valid but undefinded state'
If that doesn't work for you (still stack thrashing / no move assignment operator, etc.), you should probably go for placement new, explicitly calling the destructor like @tomer zeitune suggests:
o.~Object(); // cleanup
new (&o) Object();
Explicit call to destructor is required to e.g. release all the resources managed by the object.
Upvotes: 3
Reputation: 1192
You need use placement new and call the object destructor example below
A a = A();//init
a.~A();//clear
new (&a) A();//re init
Upvotes: 3