Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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+中的内存管理模式+;_C++_Design Patterns_Memory Management - Fatal编程技术网

C++ C+中的内存管理模式+;

C++ C+中的内存管理模式+;,c++,design-patterns,memory-management,C++,Design Patterns,Memory Management,我认为我对正常(功能性)设计模式有相当丰富的经验,如中所述,我主要在java和C#中使用。在这些“托管”语言中,这几乎是完成工作所需的所有知识 但是,在C++世界中,开发人员还控制所有对象如何分配、传递和删除。我理解这些原则(我在其他文本中读过),但要决定哪种机制最适合给定的场景仍然需要我付出大量的努力——这就是与内存相关的设计模式组合的有用之处 例如,昨天我必须创建一个类Results,它是一些对象的容器和另一类对象的集合(本例中为std::vector)。因此,有几个设计问题我无法真正回答:

我认为我对正常(功能性)设计模式有相当丰富的经验,如中所述,我主要在java和C#中使用。在这些“托管”语言中,这几乎是完成工作所需的所有知识

但是,在C++世界中,开发人员还控制所有对象如何分配、传递和删除。我理解这些原则(我在其他文本中读过),但要决定哪种机制最适合给定的场景仍然需要我付出大量的努力——这就是与内存相关的设计模式组合的有用之处

例如,昨天我必须创建一个类
Results
,它是一些对象的容器和另一类对象的集合(本例中为std::vector)。因此,有几个设计问题我无法真正回答:

  • 我应该通过值还是通过智能指针返回这个类
  • 在类内部,向量和对象应该是普通成员,还是应该再次存储为智能指针
  • 在向量中,我应该直接存储对象,还是再次智能指向它们
  • 在我的结果类上定义的getter应该返回什么(即值、引用或智能指针)
  • 当然,智能指针很酷,但它们会造成语法混乱,我不相信对每个对象使用malloc是否是最佳方法


    如果能回答以上的具体问题,我将不胜感激,但对于一些关于内存相关设计模式的更长、更一般的文本,我将更加感激——这样我也可以解决我周一遇到的问题

    您所有问题的答案都是一样的:这取决于您是否需要引用语义或值语义(需要考虑一些注意事项)

    如果需要引用语义,这是Java和C#等语言中默认使用
    关键字声明的UDT(用户定义的数据类型),则必须使用智能指针。在这种情况下,您希望多个客户机持有特定对象的安全别名,其中“安全”一词封装了以下两个要求:

  • 避免悬挂引用,这样您就不会试图访问不再存在的对象
  • 避免对象超过对它们的所有引用,这样就不会泄漏内存
  • 这就是智能指针所做的。如果您需要引用语义(如果您的算法不足以在需要共享所有权的情况下显著增加引用计数的开销),那么您应该使用智能指针

    例如,当您希望同一对象成为多个集合的一部分时,确实需要引用语义。更新一个集合中的对象时,您希望所有其他集合中的同一对象的表示形式都得到一致更新。在本例中,您将智能指针存储到这些集合中的对象。智能指针封装对象的标识,而不是其值

    但如果您不需要创建别名,那么值语义可能是您应该依赖的。当你用自动存储声明一个对象(即堆栈)时,这是默认情况下C++得到的。

    一个要考虑的是STL集合存储值,所以如果你有一个<代码>向量 >,那么<>代码> t>代码>的副本将被存储在你的<代码>矢量< /代码>中。始终假定您不需要引用语义,如果您的对象很大且复制成本很高,那么这可能会成为开销

    为了限制这种情况的可能性,C++11附带了移动操作,当不再需要对象的旧副本时,可以通过值高效地传输对象


    现在,我将尝试使用上述概念更直接地回答您的问题

    1) 我应该通过值还是通过智能指针返回这个类

    这取决于您是否需要引用语义。该函数对该对象有什么作用?该函数返回的对象是否应该由多个客户端共享?如果是,则使用智能指针。如果没有,是否可以定义有效的移动操作(几乎总是这样)?如果是,则按值计算。如果不是,则使用智能指针

    2) 在类内部,向量和对象应该是普通成员,还是应该再次存储为智能指针

    最有可能是普通成员,因为向量在概念上通常是对象的一部分,因此它们的生存期与嵌入它们的对象的生存期相关联。在这种情况下,您很少需要引用语义,但如果需要,请使用智能指针

    3) 在向量中,我应该直接存储对象,还是再次智能指向它们

    回答与第1点相同):您需要共享这些对象吗?你应该为这些对象存储别名吗?是否希望在引用这些对象的代码的不同部分中看到对这些对象的更改?如果是,则使用共享指针。如果没有,是否可以有效地复制和/或移动这些对象?如果是(大多数情况下),则存储值。如果不是,则存储智能指针

    4) 在我的结果类上定义的getter应该返回什么(即值、引用或智能指针)

    答案与第2点相同):这取决于您计划对返回的对象执行什么操作:您希望代码的许多部分共享它们吗?如果是,则返回智能指针。如果它们仅由一个部分独占,则按值返回,除非移动/复制这些对象过于昂贵或根本不允许(不太可能)。在这种情况下,返回一个智能指针


    作为一个旁注,请注意C++中的智能指针比java/C语言的要复杂一些。