我试图将unique_ptr
的向量生成到Example
类,由于某种原因,每次调用emplace_back()
时,对象都会被解构两次。我认为如果我在这里展示代码,你就更容易理解了:
#include <vector>
#include <iostream>
#include <memory>
class Example;
typedef std::unique_ptr<Example> ExampleUPointer;
std::vector<ExampleUPointer> ExampleList;
class Example {
short index;
public:
Example()
: index (ExampleList.size())
{
ExampleList.emplace_back(std::make_unique<Example>(*this));
printf("Example %d was constructed\n", index);
}
~Example() {
printf("Example %d was deconstructed\n", index);
}
};
然后继续在Example
类的main()
中创建五个对象。这是输出:
Example 0 was constructed
Example 1 was constructed
Example 2 was constructed
Example 3 was constructed
Example 4 was constructed
Example 4 was deconstructed
Example 3 was deconstructed
Example 2 was deconstructed
Example 1 was deconstructed
Example 0 was deconstructed
Example 0 was deconstructed
Example 1 was deconstructed
Example 2 was deconstructed
Example 3 was deconstructed
Example 4 was deconstructed
为什么会发生这种情况?
发布于 2021-01-09 18:41:55
std::unique_ptr
拥有它所指向的东西。因此,对象的构造函数(它已经有一个所有者--不管是什么构造对象)创建一个指向自身的有效的唯一指针是没有任何意义的。当然这不是你要做的。正如Sam的答案所说,您正在创建一个全新的Example
对象,一个副本,并将其添加到向量中。
一种选择是让向量不拥有对象。只需将原始指针存储在向量中即可。
std::vector<Example*> ExampleList;
...
Example()
{
ExampleList.emplace_back(this);
}
这将要求您确保Example
对象至少存在于向量中指向它的指针。您可以让析构函数从向量中自动删除它。
另一个选项是拥有一个工厂函数,该函数创建对象,将其添加到向量(然后矢量将拥有该对象),并返回指向该对象的指针。对象的生存期现在由向量来维护:
class Example;
std::vector<std::unique_ptr<Example>> ExampleList;
class Example {
public:
static Example *create()
{
// Create a new Example object and add it to the vector
// The unique_ptr in the vector has ownership of the object
ExampleList.push_back(std::make_unique<Example>());
// Return a pointer to the object
return ExampleList.back().get();
}
private:
// Can't call directly
Example() { ... }
};
发布于 2021-01-09 19:36:04
每次使用int构造函数创建对象时,该构造函数通过调用复制构造函数创建另一个完全不同的对象。
Example()
: index (ExampleList.size())
{
ExampleList.emplace_back(std::make_unique<Example>(*this)); //<--- here
printf("Example %d was constructed\n", index);
就在那儿。你做了第二个目标。
因此,使用int构造函数构造5个对象,用复制构造函数构造5个对象,然后销毁10个对象。
复制的对象具有与int构造的对象相同的索引。这就是复制的意思。
发布于 2021-01-09 18:28:15
ExampleList.emplace_back(std::make_unique<Example>(*this));
如果你用纸和铅笔算出结果,你会发现Example
的第二个实例就在这里被复制了。
但是,您的类有一个默认的复制构造函数,当然,它不会记录任何内容。
因此,您真正看到的是调用原始对象和副本的析构函数。复制构造没有任何记录。
在添加一个显式复制构造函数之后,您将看到正在发生的事情的全貌,该构造函数记录对象的哪个实例得到复制构造。
,我把他们的unique_ptr加到向量上?
不,你不能那么做。您正在使用make_unique
(因为它就是这样做)在动态范围内创建每个对象的副本,并将新构造的副本的unique_ptr
添加到向量中。
https://stackoverflow.com/questions/65649614
复制相似问题