有没有一种方法可以使用placement new将堆栈的对象分配给分配的内存?

时间:2018-10-31 11:01:05

标签: c++ c++11 reference placement-new

这是我的程序:

#include <iostream>

using namespace std;

class Object {
public:
    Object() { cout << "Object constructor!" << endl; }
    ~Object() { cout << "Object destructor!" << endl; }
    Object(const Object& obj) { information = obj.information; cout << "Copy constructor!" << endl; }
    void setInformation(const string info) { information = info; }
    string getInformation() const { return information; }
private:
    string information;
};

class Storage {
public:
    Storage() { object = static_cast<Object*>(operator new(sizeof(Object))); }
    ~Storage() { operator delete(object); }

    void setObject(const Object& obj) {
        // Todo: assign obj to the allocated space of the pointer object
    }
private:
    Object* object;
};

int main()
{
    Object o;
    o.setInformation("Engine");
    Storage storage;
    storage.setObject(o);
    return 0;
}

在存储中,我正在分配空间来存储类型为Object的一个对象而不创建它。我正在使用new分配内存,并在析构函数中释放它。我知道我可以用

object = new(object) Object()

构造一个对象。但是我可以将已经创建的对象放入内存中吗?在我的情况下,调用方法setObject()。如果是,使用这种内存管理会遇到什么问题?预先感谢。

3 个答案:

答案 0 :(得分:2)

实现您要实现的行为的最简单方法是使用C ++ 17中的std::optional。它可以让您为Object“保留”内存,而无需构造它,并且不使用堆。它还将处理所有构造函数和析构函数调用。

这也可以在没有std::optional的情况下完成,但实际上您必须自己实现类似的解决方案。无论如何,您都将需要一个额外的成员来指定是否构造对象,以便您可以正确地处理销毁和分配。

然后您的setObject方法将如下所示:

void setObject(const Object& obj) {
    if (constructed) {
        *object = obj;
    } else {
        new (object) Object(obj);
        constructed = true;
    }
}

要利用移动语义,您可以像这样修改您的方法:

void setObject(Object obj) {
    if (constructed) {
        *object = std::move(obj);
    } else {
        new (object) Object(std::move(obj));
        constructed = true;
    }
}

请注意,现在setObject接受它的参数按值,因此它可以与lvalue和rvalue引用一起使用以构造参数,然后将其移入成员。

答案 1 :(得分:1)

placement new是一个非常高级的构造,而实际上指向未初始化内存的Object*的想法相当令人恐惧。我可以建议您让您的生活更轻松吗?

class Storage {
    void setObject(const Object& obj) {
        if (object) {
            *object = obj;
        } else {
            object.reset(new Object(obj));
        }
    }
private:
    std::unique_ptr<Object> object;
};

这需要在Object类上使用复制构造函数和赋值运算符,但它是C ++惯用的语言。在所示的Object实现中,编译器提供的默认实现已经可以了。

答案 2 :(得分:0)

只需要澄清一下:

  

但是我可以在内存中放置一个已经创建的对象吗?

不,您不能。没有办法在C ++中移动对象到内存中。对于普通可复制类型,您可以复制(例如,通过memcpymemmove)其内存表示形式。但这实际上并没有任何作用。而且,您的Object类是不可复制的。

您可以移动的是对象的内容,这就是移动语义的作用。

相关问题