C++:删除结构?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3001336/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:44:39  来源:igfitidea点击:

C++: Delete a struct?

c++memory-managementheap

提问by Nick Heiner

I have a struct that contains pointers:

我有一个包含指针的结构:

struct foo
{
    char* f;
    int* d;
    wchar* m;
}

I have a vector of shared pointers to these structs:

我有一个指向这些结构的共享指针向量:

vector<shared_ptr<foo>> vec;

vecis allocated on the stack. When it passes out of scope at the end of the method, its destructor will be called. (Right?) That will in turn call the destructor of each element in the vector. (Right?) Does calling delete foodelete just the pointers such as foo.f, or does it actually free the memory from the heap?

vec在堆栈上分配。当它在方法结束时超出范围时,将调用其析构函数。(对吗?)这将依次调用向量中每个元素的析构函数。(对吗?)调用delete foodelete 只是指针foo.f,还是实际上从堆中释放内存?

回答by bshields

delete foo;

will delete the memory allocated to the foo structure, which includes the three pointers. But the memory pointed to by the pointers themselves will only be deleted if you implement a destructor that explicitly deletes them.

将删除分配给 foo 结构的内存,其中包括三个指针。但是指针本身指向的内存只有在您实现显式删除它们的析构函数时才会被删除。

回答by CB Bailey

If you have dynamically allocated foo, e.g.:

如果您已动态分配foo,例如:

foo* f = new foo;

then delete fwill destroy the dynamically allocated fooobject including the pointers it contains but notanything pointed to by the pointers, if they do indeed point at dynamically allocated objects or arrays of objects.

然后delete f会破坏动态分配foo,包括它所包含的指针,但对象不是任何由指针指向的,如果他们在动态分配的对象或对象的数组确确实实点。

If you've assigned a dynamically allocated fooobject (i.e. the result of new foo) to a shared_ptr(assuming tr1 or boost) then when the last shared_ptrreferring to that object goes out of scope deletewill be called on the pointer originally returned by new fooautomatically. You don't have to do this manually.

如果您已将动态分配的foo对象(即 的结果new foo)分配给 a shared_ptr(假设 tr1 或 boost),那么当最后一个shared_ptr引用该对象的对象超出范围时,delete将在最初由new foo自动返回的指针上调用。您不必手动执行此操作。

If your object (foo) contains pointers to dynamically allocated objects that it owns (so need deallocating at the end of the lifetime of the foo), then it's highly recommended that you write a destructor to deallocate these objects in the correct way (which will depend on how they are allocated).

如果您的对象 ( foo) 包含指向它拥有的动态分配对象的指针(因此需要在 生命周期结束时解除分配foo),那么强烈建议您编写一个析构函数以正确的方式解除分配这些对象(这将取决于它们是如何分配的)。

Once you've written a destructor you need to consider whether you need to write a copy constructor and copy-assingment operator. As you are using a vector of shared pointers you may decide that your objects should not be copied. If so you can declare these as private and need not provide an implementation.

编写析构函数后,您需要考虑是否需要编写复制构造函数和复制赋值运算符。当您使用共享指针向量时,您可能会决定不应复制您的对象。如果是这样,您可以将这些声明为私有,而无需提供实现。

You should also consider one or more constructors to ensure that your pointer members are initialized. If the pointer members are never initialized then if they are not assigned to during the lifetime of a foothen they will neither be null, nor point to a valid object and this is likely to cause an error in your destructor.

您还应该考虑一个或多个构造函数以确保您的指针成员被初始化。如果指针成员从未初始化,那么如果它们在 a 的生命周期内没有被分配,foo那么它们既不会为空,也不会指向有效对象,这可能会导致析构函数出错。

回答by Edward Strange

It only deletes the pointers.

它只删除指针。

回答by Brian R. Bondy

You don't call delete fwhere f is an object of type fooif fis stack allocated. You also don't call delete fon a heap allocated object of type fooif that address is stored in a shared pointer. shared_ptrobjets will call deletefor you when the last reference is freed.

如果是堆栈分配的,则不会调用delete fwhere f 是类型对象。如果该地址存储在共享指针中,您也不会调用类型为堆的分配对象。 当最后一个引用被释放时,对象会调用你。foofdelete ffooshared_ptrdelete

Since your vector stores smart pointers they will also fall out of scope when your vector falls out of scope and the foodestructor will be called and associated memory freed. The memory of foois only the size of 3 pointers though. Not what those pointers contain.

由于您的向量存储智能指针,当您的向量超出范围时,它们也会超出范围,并且foo析构函数将被调用并释放相关内存。的内存foo只有 3 个指针的大小。不是那些指针包含的内容。

If the members of fooare heap allocated, then you will need to deletethose separately. For example maybe within the foo destructor if the memory they point to is not shared between objects.

如果 的成员foo是堆分配的,那么您将需要delete单独分配这些成员。例如,如果它们指向的内存未在对象之间共享,则可能在 foo 析构函数中。



When it passes out of scope at the end of the method, its destructor will be called. (Right?)

当它在方法结束时超出范围时,将调用其析构函数。(对?)

Right.

对。

That will in turn call the destructor of each element in the vector. (Right?)

这将依次调用向量中每个元素的析构函数。(对?)

Right. The destructor of the smart pointer.

对。智能指针的析构函数。

or does it actually free the memory from the heap?

还是它实际上从堆中释放了内存?

It calls the destructor of the smart pointer, if there are no more references to that pointer then the object it contains will be deleted and its memory will be freed.

它调用智能指针的析构函数,如果不再有对该指针的引用,那么它包含的对象将被删除并释放其内存。

回答by AnT

There appears to be some terminological mixup in your question. Destructor of the vector will call destructors for shared_ptrelements, which in turn will internally perform deleteon their stored pointers (if necessary).

您的问题中似乎存在一些术语混淆。向量的析构函数将调用shared_ptr元素的析构函数,这些析构函数又将在内部delete对其存储的指针执行(如有必要)。

Calling delete foo, where foois a pointer to struct foo, will call the destructor of struct fooand then deallocate memory occupied by *foo.

调用delete foowherefoo是指向 的指针struct foo,将调用 的析构函数,struct foo然后释放其占用的内存*foo

Destructor of the above struct foodoes absolutely nothing. It is trivial. If will not make any attempts to deallocate memory pointed by struct foo::for any other members. Why would it? It does not and cannot know whether that memory should be deallocated.

上面的析构struct foo函数完全不做任何事情。这是微不足道的。If 不会尝试释放由struct foo::f或任何其他成员指向的内存。为什么会呢?它不知道也不能知道是否应该释放该内存。

In fact, because struct foo::~foois trivial, the compilers will not normally even attempt to call it.

事实上,因为struct foo::~foo是微不足道的,编译器通常甚至不会尝试调用它。

回答by Greg Domjan

When it [vec] passes out of scope at the end of the method, its destructor will be called. (Right?)
Correct

当 [vec] 在方法结束时超出范围时,将调用其析构函数。(对吗?)
正确

That will in turn call the destructor of each element in the vector. (Right?)
Correct, this will delete the shared_ptr elements in the container, and if they are the last ones also the items they are sharing.

这将依次调用向量中每个元素的析构函数。(对吗?)
正确,这将删除容器中的 shared_ptr 元素,如果它们是最后一个,那么它们共享的项目也会被删除。

Does calling delete foo ...?
You cannot delete foo, it's a struct. You can delete an instance of foo.
Calling delete calls the destructor and frees the memory for the foo struct.

调用 delete foo ... 吗?
你不能删除 foo,它是一个结构体。您可以删除 foo 的实例。
调用 delete 调用析构函数并为 foo 结构释放内存。

Does the foo destructor delete just the pointers such as foo::f, or does it actually free the memory from the heap?
That depends on the destructo, in this case you have a default destructor and so...
No, In the following example code you can see the some of the reasons why the default destructor associated with foo cannot cleanup any pointer referred items automatically.

foo 析构函数是否只删除了诸如 foo::f 之类的指针,还是实际上从堆中释放了内存?
这取决于析构函数,在这种情况下,您有一个默认析构函数,所以...
不,在下面的示例代码中,您可以看到与 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;
}