Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 浅层和深层析构函数?_C_Memory Management_Dynamic Memory Allocation_Allocation - Fatal编程技术网

C 浅层和深层析构函数?

C 浅层和深层析构函数?,c,memory-management,dynamic-memory-allocation,allocation,C,Memory Management,Dynamic Memory Allocation,Allocation,想象一个列表a,有一个复制构造函数,用于执行深度复制的列表。如果b是从a复制的列表深度,则可以使用简单的析构函数销毁这两个列表。这个析构函数应该使用深度销毁 typedef struct list { void * first; struct list * next } list; struct list * list_copy_constructor(const struct list * input) REQUIRE_RETURNED_VALUE_CAPTURE; void list_d

想象一个列表a,有一个复制构造函数,用于执行深度复制的列表。如果b是从a复制的列表深度,则可以使用简单的析构函数销毁这两个列表。这个析构函数应该使用深度销毁

typedef struct list { void * first; struct list * next } list;

struct list * list_copy_constructor(const struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

void list_destructor(struct list * input);
现在假设您将列表的复制构造函数重命名为列表的深度复制构造函数,并为列表添加另一个浅复制构造函数

/**  Performs shallow copy. */
struct list * list_shallow_copy_constructor(const struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

/**  Performs deep copy. */
struct list * list_deep_copy_constructor(const struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

/**  Be warned performs deep destruction. */
void list_destructor(struct list * input);
执行深度销毁的析构函数可以与深度复制构造函数调用配合使用

一旦你对列表使用了浅层复制构造函数,你需要知道两个列表中哪一个拥有元素,然后其中一个列表拥有元素,可以用析构函数销毁,但是对于不拥有元素的列表,我需要用我需要创建的浅层析构函数来销毁它,在销毁拥有元素的列表之前

/**  Performs shallow copy. */
struct list * list_shallow_copy_constructor(const struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

/**  Performs deep copy. */
struct list * list_deep_copy_constructor(const struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

/**  Performs shallow destruction. */
void list_shallow_destructor(struct list * input);

/**  Performs deep destruction. */
void list_deep_destructor(struct list * input);

但是,问题是,我不认为浅层析构函数是参考书目中的一个术语,所以我认为我可能做错了什么。我做错什么了吗?例如,我是否应该使用智能指针而不是深浅的析构函数?

< P>深或浅的概念只存在于程序员的头脑中,而C++中则是非常随意的。默认情况下,当对象被销毁时,原始指针成员不会被深度销毁,您可以将其称为浅层,但您可以在对象析构函数中编写额外的代码来进行深度销毁。另一方面,任何具有析构函数的成员都会调用它们的析构函数,您可能会调用deep,这是无法避免的。完全相同的机制适用于默认的复制和赋值,因此同样不可能说一个对象一眼就完全被复制或销毁了

因此,区别实际上不是对象析构函数的属性,而是它们的成员

当然,现在的问题又是关于C的,但仍然提到了智能指针。在C语言中,你必须决定你想要实现什么样的哲学,因为没有破坏的概念。如果您遵循类似C++的理念,为每种类型的成员提供销毁函数,并让它们进行深度调用

已经说过,你可能考虑的一些策略可能会产生一个更简洁的模型:

如果特定容器的/all/members为owned或/all/not owned,那么容器中是否销毁/all/children的简单标志就是一个适当的模型

如果/all/对象与另一个容器共享,或者这可能是特定内容集的最后一个/唯一一个这样的容器,则可以保留共享容器的循环列表。当析构函数意识到它是最后一个可以销毁/所有/内容的容器时。另一方面,您可以简单地通过共享一个容器实例的ptr来实现这个模型,当释放最后一个指针时,容器就会被销毁

如果容器中的单个项目可以以任意方式共享,则将其作为每个内容项目的共享ptr容器。这是最健壮的模型,但在内存使用方面可能会有成本。最终,在某些地方,需要有一个引用计数,尽管裁判的循环列表也很好,但是在C++中使用Stub实现线程间的互斥是困难的,但是在您自己的C对象中,这可能是子对象中的计数器成员。 但是,问题是,我不认为浅层析构函数是参考书目中的一个术语,所以我认为我可能做错了什么。我做错什么了吗

析构函数或C just myobject_destroymyobject*中的析构函数的作用是清理实例所持有的内存、操作系统处理的资源等等。。。。您需要浅层析构函数还是深层析构函数取决于您决定实现对象的方式,只要它完成清理工作


如果你使用现代C++堆栈分配,智能指针是你的朋友,因为他们自己管理内存。

如果你想要共享元素的列表被正确破坏,你不能简单地使用浅的析构函数。使用浅层析构函数销毁所有元素会导致元素仍然驻留在内存中并泄漏。将其中一个列表标记为深析构函数而其他列表标记为浅析构函数看起来也不太好。如果您首先使用深度析构函数销毁列表,其他人将有悬挂的指针,您可以意外访问这些指针。所以看起来浅层析构函数并不是一个公认的术语,因为它并没有什么用处。您只有析构函数:用于销毁对象概念上拥有的内容的函数

现在,对于共享列表中的元素和销毁时间共享指针中的所有内容的特定任务,似乎是一个合理的解决方案。共享指针在概念上是指向由两个元素组成的结构的指针:实际的对象列表元素和引用
电子计数器。复制共享指针会增加计数器;如果计数器降为0,则销毁共享指针会减少计数器,并使用object&counter销毁结构。在这种情况下,每个列表都拥有其共享指针的副本,但列表元素本身属于共享指针而不是列表。由于共享指针销毁语义,销毁列表拥有的所有共享指针副本不会有问题。除非没有剩余的引用,否则析构函数不会释放内存,因此不需要区分浅析构函数和深析构函数,因为共享指针会及时自动删除自己。

正如您已经怀疑的,您的设计很奇怪。想一想:如果你要复制一个列表,为什么不直接拿一个指针呢?在课堂之外,浅拷贝没有任何用处,在课堂上,解释什么是深拷贝才是有用的

您可能希望多个用户拥有独立的列表,这些列表可以彼此独立地使用和销毁,或者希望一个用户拥有该列表,而其他用户只指向该列表。与简单指针相比,浅层复制的想法没有任何优势,但处理起来要复杂得多

实际上有用的是有多个列表,但有共享数据,其中每个用户都有自己的共享列表副本,可以单独使用和销毁,但指向相同的数据,并且只有在最后一个用户销毁数据后才会真正解除分配。这是一个非常常见的模式,通常由一个调用的算法来处理,它是由许多库和语言实现的,比如Python、GLIB,甚至在C++中作为智能指针STD::SyrdypTr.< /P> 如果您使用的是C,那么您可能希望向结构列表中添加对引用计数的支持,这并不困难:只需添加一个字段unsigned reference\u count;并在分配时将其设置为1。销毁时减少,但只有在引用_count==0时才真正释放,在这种情况下,没有更多用户,您必须执行深度释放。您仍然只有一个析构函数,但有两个复制构造函数:

/**  Performs shared copy.
 *
 * Actually, just increments reference_count and returns the same pointer.
 */
struct list * list_shared_copy_constructor(struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

/**  Performs deep copy.
 *
 * reference_count for the new copy is set to 1.
 */
struct list * list_deep_copy_constructor(const struct list * input)
REQUIRE_RETURNED_VALUE_CAPTURE;

/**  Performs destruction. */
void list_shallow_destructor(struct list * input);

如果你实际使用C++,正如你在你的问题中暗示的那样,那么简单地使用STD::SyrdyPtR.< /P>对不起,为什么你把C++标签替换为C++标签?大概是因为拷贝构造器不在C中。请告诉我拷贝构造器是如何在C中:@ L.F.C++使用这个术语,但是它不拥有它。C中的自定义ADT可以有一个ADT_克隆函数,这是一个复制构造函数。它从现有对象创建一个新对象-您可能希望添加一些代码示例。它应该避免混淆C++的用法。一天中的概念,深度或浅的概念只存在于程序员的头脑中,而C++中则是非常随意的。