(Re)在cpp中初始化没有复制构造函数的对象

时间:2019-02-12 08:09:22

标签: c++ stack

这个问题是针对嵌入式系统的!

我具有以下用于初始化对象的选项:

Object* o = new Object(arg);

这会将对象放入堆中并返回指向它的指针。我不想在嵌入式软件中使用动态分配。

Object o = Object(arg);

这将在堆栈中创建一个新对象,然后将其复制到对象o中,然后将其删除。如果对象足够大以适合RAM而不适合堆栈,则可能导致堆栈溢出。我已经看到这种情况在关闭优化的情况下发生了,我没有探索启用优化的情况是否与此不同。

Object o(arg);

这将创建对象而不进行复制,但是如何再次“初始化” o

对于嵌入式,我更喜欢最后一个选项,因为不使用堆,并且堆栈中没有临时对象可以引起堆栈溢出。

但是,由于以下原因,我对如何再次重新初始化对象感到困惑:

o.Object(arg)

不允许。

我可以创建一个名为init(arg)的方法并调用

o.init(arg)

Object::Object(arg)进行相同的初始化,但是我不希望不必使用我需要记住的“非标准”名称创建一个额外的方法。

是否有一种方法可以调用已创建对象的构造函数,以在不进行复制的情况下再次对其进行初始化?

3 个答案:

答案 0 :(得分:2)

请考虑在对象的当前内存中使用new放置。这将在当前使用的内存中初始化一个新对象,而不分配新内存。那可能是您的解决方案。例如:

new (&o) Object(args)

尝试一下:

#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返回10010049,这是正确的。

答案 1 :(得分:1)

您需要使用placement new并调用下面的对象析构函数示例

A a = A();//init
a.~A();//clear
new (&a) A();//re init

答案 2 :(得分:1)

步骤1.获得一个可以正常工作的编译器(可以识别将对象初始化到位的最明显的机会),并且至少支持C ++ 11。

第2步。对于初始化,请使用:

auto o = Object(arg); // won't copy ever with optimization turned on

如果您需要使用新参数重新分配给构造函数:

o = Object(arg1); // calls move asignment operator

如果您需要用其他对象的值覆盖该值(以后不打算使用该对象,则不打算使用该值:

o = std::move(o1); // o1 is the other Object, afterwards o1 is left in 'valid but undefinded state'

如果这对您不起作用(仍然出现堆栈抖动/没有移动分配运算符等),则您可能应该进行新的放置,像@tomer zeitune建议的那样显式调用析构函数:

o.~Object(); // cleanup
new (&o) Object();

需要明确调用析构函数,例如释放对象管理的所有资源。