[英]Proper way to emplace_back object into std::list
我有一个包含各种成员的类(主要是int,float和一些动态容器)。 我有一个std :: list myclassobjects。 在设置所有参数后,在此类的构造函数中调用
myclassobjects.emplace_back(*this)
这有效,并且似乎不会引起分配问题; 我从来没有sigsegv问题或类似问题。 但是,我并不完全相信这是正确的做法,或者它不会导致缓慢的刻录内存泄漏。
此方法安全使用还是会导致内存泄漏? 如果是,构造对象并将其立即放入std :: list的“正确”方法是什么?
首先, 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
并将其参数转发给构造函数。
确实不可能将对象存储在std::list
或任何其他容器中。 根据对象的标准定义,对象是存储区域 。 存储的区域不能存储,它只是为 。
假设X是一个现有对象。 容器本身不能存储X,但是可以某种方式与X相关的值。 有两种选择。
由于您要使用*this
,因此要存储副本。 这可能是您需要的,也可能不是。
要存储裸露的指针,您必须要emplace_back(this)
,当然emplace_back(this)
更改列表的类型。 这很危险,因为当X不再存在时,您的列表可能仍然有指向它的悬空指针。 您需要确保它不会发生。
您可能要考虑将共享指针,但如果你想通过继承,使之enable_shared_from_this
,要知道, shared_from_this
是在构造函数中使用危险的事情 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.