3

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?

Carlos
  • 105
  • 2
  • 14
  • *"This creates a new object in the stack and then copies it to object o and removes it after."* - Only if your compiler is well and truly utterly daft.... Ah, I see you compiled without optimizations... – StoryTeller - Unslander Monica Feb 12 '19 at 08:10
  • 1
    Does your class support *move* semantics or does it have a `swap(...)` function? – Galik Feb 12 '19 at 08:13
  • 3
    If you define the object as `Object o;` then just *assign* to it to "initialize" it again? As in `o = Object();`. – Some programmer dude Feb 12 '19 at 08:13
  • 3
    Out of curiosity, why do you need to "initialize" it again? – StoryTeller - Unslander Monica Feb 12 '19 at 08:17
  • @StoryTeller Since I'm programming for embedded I prefer to have control over the memory and I place all the variables of "big" things outside any function so they are allocated on compile time and I know they fit. I like to initialize them in a init function since the code is a bit more tidy in my opinion. In some cases also it may be needed to reinitialize an object if I put the processor to sleep and some hardware requires re initialization as well as the software. – Carlos Feb 12 '19 at 09:17

3 Answers3

3

You need use placement new and call the object destructor example below

A a = A();//init
a.~A();//clear
new (&a) A();//re init
tomer zeitune
  • 1,080
  • 1
  • 12
  • 14
3

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.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • error: #384: no instance of overloaded "operator new" matches the argument list In which version of C++ was this added? – Carlos Feb 12 '19 at 09:11
  • Some info on placement new can be found here : https://www.geeksforgeeks.org/placement-new-operator-cpp/ It's quite old . I think C++-98 should already have it. Also stack overflow question on placement new: https://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new – Pawel Brzezinski Feb 12 '19 at 09:17
  • note that this does not automatically call the destructor on the first instance of `A` – bb1950328 Jul 02 '23 at 09:55
3

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.

paler123
  • 976
  • 6
  • 18
  • We do not know if arbitrary "Object" provided without definition has any move assignment operators or not. – Öö Tiib Feb 12 '19 at 09:04
  • The compiler still places the object in the stack to move it later when I turn on optimizations to level O3. Unfortunately I don't seem to be able to use `o = Object(arg1);` – Carlos Feb 12 '19 at 09:13