我有一个包含指针的结构:
struct foo
{
char* f;
int* d;
wchar* m;
}
我有一个指向这些结构的共享指针的向量:
vector<shared_ptr<foo>> vec;
在堆栈上分配了 vec
。当它在方法结束时超出范围时,将调用其析构函数。 (对吗?)然后将调用向量中每个元素的析构函数。 (对吗?)调用delete foo
只删除foo.f
之类的指针,还是实际上从堆中释放了内存?
答案 0 :(得分:15)
delete foo;
将删除分配给foo结构的内存,其中包括三个指针。但是如果你实现了一个明确删除它们的析构函数,指针本身指向的内存只会被删除。
答案 1 :(得分:10)
如果您已动态分配foo
,例如:
foo* f = new foo;
然后delete f
会破坏动态分配的foo
对象,包括它包含的指针但不指针指向的任何东西,如果它们确实指向动态分配的对象或对象数组。
如果您已将动态分配的foo
对象(即new foo
的结果)分配给shared_ptr
(假设为tr1或者提升),那么最后shared_ptr
引用该对象超出范围delete
将在new foo
最初返回的指针上自动调用。您不必手动执行此操作。
如果您的对象(foo
)包含指向它所拥有的动态分配对象的指针(因此需要在foo
的生命周期结束时解除分配),那么强烈建议您编写析构函数以正确的方式释放这些对象(这将取决于它们的分配方式)。
一旦编写了析构函数,就需要考虑是否需要编写复制构造函数和copy-assingment运算符。当您使用共享指针向量时,您可能决定不应复制您的对象。如果是这样,您可以将这些声明为私有,无需提供实现。
您还应该考虑一个或多个构造函数,以确保您的指针成员已初始化。如果指针成员永远不会被初始化,那么如果它们在foo
的生命周期内没有被赋值,那么它们既不会为空,也不会指向有效对象,这很可能会导致析构函数出错。 / p>
答案 2 :(得分:1)
它只删除指针。
答案 3 :(得分:1)
如果delete f
为堆栈分配,则不调用foo
其中f是f
类型的对象。如果该地址存储在共享指针中,则也不要在类型为delete f
的堆分配对象上调用foo
。 shared_ptr
objets将在释放最后一个引用时为您调用delete
。
由于向量存储智能指针,当向量超出范围并且将调用foo
析构函数并释放相关内存时,它们也将超出范围。 foo
的内存只有3个指针的大小。不是那些指针包含的内容。
如果foo
的成员是堆分配的,那么您需要单独delete
这些成员。例如,可能在foo析构函数内,如果它们指向的内存不在对象之间共享。
当它在方法结束时超出范围时,将调用其析构函数。 (右?)
右。
这将依次调用向量中每个元素的析构函数。 (右?)
右。智能指针的析构函数。
还是实际上从堆中释放了内存?
它调用智能指针的析构函数,如果没有更多对该指针的引用,那么它所包含的对象将被删除,其内存将被释放。
答案 4 :(得分:1)
你的问题似乎有一些术语混淆。向量的析构函数将调用shared_ptr
元素的析构函数,而后者将在内部对其存储的指针执行delete
(如有必要)。
调用delete foo
,其中foo
是指向struct foo
的指针,将调用struct foo
的析构函数,然后释放*foo
占用的内存。
上述struct foo
的析构函数绝对没有任何作用。这是微不足道的。如果不会尝试释放struct foo::f
或任何其他成员指向的内存。为什么会这样?它不会也无法知道是否应该释放该内存。
事实上,因为struct foo::~foo
是微不足道的,编译器通常不会尝试调用它。
答案 5 :(得分:0)
当[vec]在方法结束时超出范围时,将调用其析构函数。 (右?)强>
正确
这将依次调用向量中每个元素的析构函数。 (右?)强>
更正,这将删除容器中的shared_ptr元素,如果它们是最后的元素,也是它们共享的项目。
调用delete foo ...?
你不能删除foo,它是一个结构。您可以删除foo的实例
调用delete会调用析构函数并释放foo结构的内存。
foo析构函数是否只删除foo :: f之类的指针,还是实际上从堆中释放了内存?
这取决于destructo,在这种情况下,你有一个默认的析构函数,所以...
不,在下面的示例代码中,您可以看到与foo关联的默认析构函数无法自动清除任何指针引用项的一些原因。
{
char ca='a', *cb=new char;
int *i = (int*)malloc(sizeof(int));
foo a;
shared_ptr<foo> b = new foo();
a.f = &ca;
a.d = i;
b.f = cb;
}