我有一个有各种成员的类(主要是整数,浮点数和一些动态容器)。我有一个std :: list myclassobjects。在设置我调用的所有参数
之后,在该类的构造函数中myclassobjects.emplace_back(*this)
这有效并且似乎不会导致任何分配问题;我从来没有过sigsegv问题或类似问题。但是,我并不完全相信这是正确的做法,或者它不会导致缓慢的内存泄漏。
此方法是否可以安全使用或是否会导致内存泄漏?如果是,那么“适当的”是什么?如何构建一个对象并立即将其放入std :: list?
答案 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相关的值。有两种选择。
由于您正在安装*this
,因此您正在存储副本。这可能是您需要的,也可能不是。
要存储裸指针,您必须emplace_back(this)
,当然还要更改列表的类型。这很危险,因为当X不再存在时,您的列表可能仍然有一个悬挂指针。你需要确保它不会发生。
您可能需要考虑存储共享指针,但如果要通过继承enable_shared_from_this
来启用它,请注意shared_from_this
is a dangerous thing to use in a constructor。