将它添加到std时呼吁对象的析构::名单
-
21-08-2019 - |
题
我有一个Foo对象,和一个std ::列表保持它的实例。我的问题是,当我添加一个新的实例列表中,它首先调用构造函数的但随后也析构函数。然后在另一实例中的析构函数(按照此指针)。
一个单个实例被添加到列表中,但因为它的析构函数被调用(与父母一起),不能被使用的对象的要求。
下面有一些简化的代码来说明这个问题:
#include <iostream>
#include <list>
class Foo
{
public:
Foo()
{
int breakpoint = 0;
}
~Foo()
{
int breakpoint = 0;
}
};
int main()
{
std::list<Foo> li;
li.push_back(Foo());
}
解决方案
当你的push_back()你的Foo对象,该对象是的复制以列表的内部数据结构,因此,析构函数和另一实例的构造函数被调用。
在C所有标准STL的容器类型由++值取他们的物品,因此将它们复制根据需要。例如,每当一个矢量需要成长,有可能的是,在载体中的所有值被复制。
也许你想存储的指针而不是列表中的对象。通过这样做,只有指针被复制,而不是对象。但是,通过这样做,你必须确保删除对象一旦你完成:
for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
delete *it;
}
list.clear();
另外,也可以尝试使用某种“智能指针”类的,例如从Boost库。
其他提示
您在这里创建一个临时富:
li.push_back( Foo() )
的push_back将复制的Foo到其内部数据结构。的push_back已经执行后,临时的Foo被破坏,这将调用析构函数。
您将需要增加的类成员,你不想提前破坏某些引用计数正确的拷贝构造函数 - 或使其私人强迫自己上的指针解
。使用此对象了解:
class Foo
{
public:
Foo(int x): m_x(x)
{
std::cout << "Constructed Object: " << m_x << ")\n";
}
Foo(Foo const& c): m_x(c.m_x+100)
{
std::cout << "Copied Object: " << m_x << ")\n";
}
~Foo()
{
std::cout << "Destroyed Object: " << m_x << ")\n";
}
};
第一主
std::list<Foo*> li;
li.push_back(Foo(1));
下面我们创建临时Foo对象和呼叫的push_back()。临时对象被复制到列表和函数返回。在此声明,则临时对象被销毁(通过析构函数)完成。当列表被破坏它也将破坏其包含的所有obejcts(foo是与析构函数的对象,从而破坏包括调用析构函数)。
所以,你应该看到的财产以后这样的:
Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101
在第二个例子中您有:
std::list<Foo*> li;
li.push_back(new Foo(1));
下面动态创建在堆上的一个对象。然后调用的push_back()。在这里,指针被复制到列表(指针没有构造函数/析构函数),所以没有什么事情发生。列表现在包含一个指向堆上的对象。当函数返回别的什么都不做。当名单被破坏它破坏(注意微妙的差异中间人破坏和删除)(指针)它包含的对象,但指针没有析构函数所以什么也没有发生任何您将导致内存泄漏。
所以,你应该看到的财产以后这样的:
Constructed Object: 1
实际发生的这里是您将传递的对象的复制在列表中,因为你的价值,而不是通过引用发送。所以被称为实际上是叫你传递给方法的push_back对象上的第一个析构函数,但一个新的实例已经被创建,然后,它现在存储在列表中。
如果您不想储存指针的富的对象的副本被创建,以富的列表,而不是对象本身的对象。当然,这样做时,你将不得不在列表的破坏正常释放内存。
使得列表保持指针而不是实例解决了被称为与析构函数的问题。但我还是想了解为什么会发生。
#include <iostream>
#include <list>
class Foo
{
public:
Foo()
{
int breakpoint = 0;
}
~Foo()
{
int breakpoint = 0;
}
};
int main()
{
std::list<Foo*> li;
li.push_back(new Foo());
}