将emplace_back对象转换为std :: list的正确方法

时间:2017-09-28 06:54:39

标签: c++ list allocation

我有一个有各种成员的类(主要是整数,浮点数和一些动态容器)。我有一个std :: list myclassobjects。在设置我调用的所有参数

之后,在该类的构造函数中
myclassobjects.emplace_back(*this)

这有效并且似乎不会导致任何分配问题;我从来没有过sigsegv问题或类似问题。但是,我并不完全相信这是正确的做法,或者它不会导致缓慢的内存泄漏。

此方法是否可以安全使用或是否会导致内存泄漏?如果是,那么“适当的”是什么?如何构建一个对象并立即将其放入std :: list?

2 个答案:

答案 0 :(得分:2)

首先,emplace_back通过转发其参数来构造一个对象。所以你最终要做的就是使用参数*this调用你的类的复制构造函数。

我试图想到一种情况,即需要在构造函数中的列表中添加对象,并且我很难过。我认为有更好的选择。

将其置于构造函数外部的列表中

只需创建如下。

myclassobjects.emplace_back(/*constructor params*/);

在C ++ 17中,这甚至返回对新创建的对象的引用

MyClass& myclass_ref = myclassobjects.emplace_back(/*constructor params*/);
do_something_with_my_class_object(myclass_ref);

这是最干净,最有效的方法。它具有额外的好处,您可以创建本地对象,而无需在需要时将它们添加到列表中。

使用将其添加到列表

的工厂方法

如果您必须拥有列表中的所有对象,并且您不希望它是副本,请使用静态工厂方法。如果列表和被叫方必须共享所有权,您可以使用std::shared_ptr列表并执行以下操作。

MyClass {
private:
    MyClass();    // private constructor forbids on the stack variables

public:
    static std::shared_ptr<MyClass> create_instance() {
        auto ptr = make_shared<MyClass>();    // We can access the constructor here
        myclass_objects.emplace_back(ptr);
        return ptr;
    }
}

另一方面,如果您的列表保证比对象上的被调用者处理程序更长,那么拥有一个包含对象的std::unique_ptr列表并返回对它们的引用更为合适

MyClass {
private:
    MyClass();    // private constructor forbids on the stack variables

public:
    // pre C++17
    static MyClass& create_instance() {
        auto ptr = make_unique<MyClass>();
        auto& ref = *ptr;    // Store ref before we move pointer
        myclass_objects.emplace_back(std::move(ptr));
        return ref;
    }

    // C++17
    static MyClass& create_instance() {
        auto ptr = make_unique<MyClass>();
        return *(myclass_objects.emplace_back(std::move(ptr)));
    }
}

当然,这些示例仅涵盖默认构造函数。因为您通常需要使用更多构造函数,所以您可能需要一个模板create_instance来将其参数转发给构造函数。

答案 1 :(得分:0)

确实无法将对象存储在std::list或任何其他容器中。根据对象的标准定义,对象是存储区域。无法存储存储区域,只需

假设X是现有对象。容器不能以某种方式存储X本身,而是存储与X相关的值。有两种选择。

  1. 存储X的副本
  2. 将(智能)指针或参考包装存储到X。
  3. 由于您正在安装*this,因此您正在存储副本。这可能是您需要的,也可能不是。

    要存储裸指针,您必须emplace_back(this),当然还要更改列表的类型。这很危险,因为当X不再存在时,您的列表可能仍然有一个悬挂指针。你需要确保它不会发生。

    您可能需要考虑存储共享指针,但如果要通过继承enable_shared_from_this来启用它,请注意shared_from_this is a dangerous thing to use in a constructor