|
|
1
67
我一直听到人们抱怨C++没有垃圾收集。我为他们感到抱歉。说真的。 C++有RAII,我总是抱怨在垃圾收集语言中找不到RAII(或者阉割RAII)。 垃圾回收能给经验丰富的C++开发人员带来什么好处?另一个工具。 马特J写得很对( Garbage Collection in C++ -- why? 我们不需要C++的特性,因为它们中的大多数都可以用C语言编码,我们不需要C特性,因为大多数都可以在汇编等中编码。 C++必须进化。 作为开发人员:我不在乎GC。我尝试了RAII和GC,我发现RAII非常优越。正如格雷格·罗杰斯在他的职位上所说( Garbage Collection in C++ -- why? 内存泄漏并不是那么可怕(至少在C++中,如果C++被使用的话,它们是罕见的)来证明GC而不是RAII。GC具有不确定性的释放/终结,只是一种 编写一个不关心特定内存选择的代码 . 最后一句话很重要:写“juste不在乎”的代码很重要。以同样的方式,在C++中,我们不关心释放源,因为RAII为我们做了,或者对象初始化,因为构造函数为我们做了,有时只需编码而不关心谁是什么内存的所有者,以及我们需要什么样的指针(共享、弱等)。 在C++中似乎需要GC。 (即使我个人看不见) C++中良好的GC使用实例有时候,在应用程序中,你有“浮动数据”。想象一个树形的数据结构,但没有人真正是数据的“所有者”(也没有人真正关心数据何时会被销毁)。多个对象可以使用它,然后丢弃它。你希望在没有人再使用它的时候释放它。 C++方法是使用智能指针。我想到了共享资源。所以每个数据都由自己的共享指针拥有。酷。问题是,当每一段数据都可以引用另一段数据时。不能使用共享指针,因为它们使用的引用计数器不支持循环引用(A指向B,B指向A)。因此,您必须了解在哪里使用弱指针(boost::weak_ptr)以及何时使用共享指针。 对于GC,您只需使用树结构数据。 缺点是你不必在意 什么时候? “浮动数据”将真正被销毁。只有它 将 摧毁。 结论最后,如果做得正确,并且与C++的当前习语兼容,GC将是一个 C++的另一个好工具 . C++是一种多范式语言:添加GC可能会使一些C++迷因为叛逆而哭泣,但最终,它可能是一个好主意,我猜想C++标准COMITEE不会让这种主要特征破坏语言,所以我们可以相信他们做出必要的工作来启用一个不干扰C++的正确的C++ GC: 像C++一样,如果你不需要一个特性,不要使用它,它不会花费你任何东西。 |
|
|
2
11
简而言之,垃圾收集在原则上与带有智能指针的RAII非常相似。如果您分配的每一块内存都位于一个对象中,并且该对象只被智能指针引用,那么您就拥有了一些接近垃圾收集的东西(可能更好)。其优点在于不必如此明智地确定范围和智能地为每个对象指定指针,并且让运行时为您完成工作。 这个问题类似于“C++如何为有经验的装配开发者提供什么?”指令和子程序消除了对它的需求,对吗?” |
|
|
3
9
随着像valgrind这样优秀的内存检查程序的出现,我认为垃圾收集作为一个安全网“以防万一”并没有多大用处,我们忘记了释放一些东西——特别是因为它对管理除内存以外的更通用的资源情况没有多大帮助(尽管这些情况不太常见)。此外,在我看到的代码中,显式地分配和释放内存(即使使用智能指针)是相当罕见的,因为容器通常是一种更简单和更好的方法。 但是垃圾收集可以潜在地提供性能优势,特别是在大量短期对象被堆分配的情况下。GC还可能为新创建的对象(与堆栈上的对象相比)提供更好的引用位置。 |
|
|
4
8
在C++中GC支持的激励因素似乎是lambda编程、匿名函数等。事实证明,lambda库受益于分配内存而不关心清理的能力。普通开发人员的好处是,编译lambda库更简单、更可靠和更快。 GC还帮助模拟无限内存;您需要删除pods的唯一原因是需要回收内存。如果您有GC或无限内存,就不再需要删除pods了。 |
|
|
5
7
委员会没有添加垃圾收集,而是添加了一些功能,使垃圾收集更安全地实现。只有时间才能判断它们是否对未来的编译器有任何影响。具体的实现可能会有很大的差异,但最有可能涉及基于可到达性的集合,这可能涉及一个轻微的挂起,具体取决于它是如何完成的。 不过,有一件事是,没有符合标准的垃圾收集器能够调用析构函数——只能默默地重用丢失的内存。 |
|
|
6
7
垃圾回收能给经验丰富的C++开发人员带来什么好处?不必追查经验不足的同事代码中的资源泄漏。 |
|
|
7
7
我不明白人们怎么能说RAII取代了GC,或者说它是非常优越的。有许多由GC处理的案例,RAII根本无法处理。它们是不同的野兽。 首先,RAII并不是防弹的:它对C++中普遍存在的一些常见故障起作用,但是在很多情况下RAII根本不起作用;它对异步事件(如UNIX下的信号)是脆弱的。从根本上讲,raii依赖于作用域:当变量超出作用域时,它会自动释放(当然,假设析构函数是正确实现的)。 下面是一个简单的例子,其中auto-ptr或raii都不能帮助您:
永远不会调用的析构函数。当然,这是一个人为的,有点做作的例子,但实际上也可能发生类似的情况;例如,当您的代码被另一个处理sigint的代码调用时,您完全无法控制它(具体的例子:matlab中的mex扩展)。这也是为什么在Python中finally不能保证某个东西的执行的原因。在这种情况下,GC可以帮助您。 其他的习语不能很好地处理这个问题:在任何一个重要的程序中,你都需要有状态的对象(我在这里用的是非常广义的“对象”一词,它可以是语言所允许的任何构造);如果你需要在一个函数之外控制状态,你就不能用raii轻松地做到这一点(这就是为什么raii对异步HR没有帮助的原因)。Onous编程)。gc有一个进程的整个内存视图,也就是它知道它分配的所有对象,并且可以异步清理。 出于同样的原因,使用GC也会更快:如果需要分配/取消分配多个对象(尤其是小对象),除非编写自定义分配器,否则GC的性能将大大优于RAII,因为GC可以一次分配/清除多个对象。一些著名的C++项目使用GC,即使在性能方面(例如,Tim Sweenie在非真实竞赛中使用GC): http://lambda-the-ultimate.org/node/1277 )GC基本上以延迟为代价增加了吞吐量。 当然,有些情况下raii比gc更好;特别是,gc的概念主要与内存有关,这不是唯一的资源。像文件之类的东西…可以很好地处理RAII。没有内存处理的语言(如python或ruby)在这些情况下确实具有类似raii的特性,btw(在python中使用语句)。当您精确地需要控制何时释放资源时,raii非常有用,例如,对于文件或锁,这种情况非常常见。 |
|
|
8
6
假设C++没有垃圾收集,这是一个普遍的错误。 融入语言 不能在C++期间使用垃圾回收。这是胡说八道。我知道那些使用BEHM收藏家的精英C++程序员在他们的工作中是理所当然的。 |
|
|
9
6
垃圾收集允许 推迟 关于谁的决定 拥有 物体。 C++使用值语义,所以RAI实际上是在离开范围时回忆对象。这有时被称为“即时GC”。 当程序开始使用引用语义(通过智能指针等)时,该语言不再支持您,您只能使用智能指针库。 GC的棘手之处在于 什么时候? 不再需要对象。 |
|
|
11
5
更简单的线程安全性和可扩展性GC的一个属性在某些情况下可能非常重要。在大多数平台上,指针的分配自然是原子的,而创建线程安全引用计数(“smart”)指针则相当困难,并且会带来大量的同步开销。因此,在多核架构中,智能指针经常被告知“不能很好地伸缩”。 |
|
|
12
3
垃圾收集实际上是自动资源管理的基础。让GC以一种难以量化的方式改变您处理问题的方式。例如,在进行手动资源管理时,需要:
在一般情况下,不存在复杂性。例如,在方法开始时打开一个文件,在结束时关闭它。或者调用方必须释放返回的内存块。 当您有多个模块与一个资源交互时,事情会很快变得复杂起来,而且还不清楚需要清理哪些模块。最终的结果是,解决问题的整个方法包括一些妥协的编程和设计模式。 在具有垃圾收集功能的语言中,可以使用 disposable 模式,您可以释放您知道已经完成的资源,但如果您不能释放它们,GC将在那里保存一天。 智能指针实际上是我提到的妥协的完美例子。除非有备份机制,否则智能指针无法避免泄漏循环数据结构。为了避免这个问题,您经常妥协并避免使用循环结构,即使它在其他方面可能是最合适的。 |
|
|
13
2
我也怀疑C++成员正在向标准中添加一个完整的垃圾收集。 但我想说,用现代语言添加/进行垃圾收集的主要原因是,好的理由太少了 反对 垃圾收集。自80年代以来,在内存管理和垃圾收集领域有了一些巨大的进步,我相信甚至有垃圾收集策略可以为您提供软实时的保证(例如,“GC不会花费超过….在最坏的情况下)。 |
|
|
14
2
智能指针可以用来实现C++中的引用计数,这是一种垃圾收集的形式(自动内存管理),但是生产GCS不再使用引用计数,因为它有一些重要的缺陷:
生产力和可靠性是主要优势。对于许多应用程序,手工内存管理需要大量的程序员工作。通过模拟无限内存机,垃圾收集将程序员从这个负担中解放出来,使他们能够集中精力解决问题,并避免一些重要的bug类(悬空指针、丢失
|
|
|
15
2
在支持GC的框架中,对不可变对象(如字符串)的引用可以以与基元相同的方式传递。考虑类(C或Java):
请注意,此代码与
内容
任何一个字符串,并且可以简单地将它们视为基元。像这样的陈述
还要注意的是,当同时调用
我认为没有任何方法可以像C++那样编写一种方法,它可以在任意多线程使用的情况下支持内存安全,而不需要使用线程同步,或者要求每个字符串变量都有自己的内容拷贝,保存在其自己的存储空间中,而这些变量可能不会被释放或重新定位。对相关变量的生存期进行循环。当然不可能定义一个字符串引用类型,它可以像
|
|
|
16
1
垃圾收集会让泄漏成为你最可怕的噩梦。
处理循环引用之类的完全成熟的GC在一定程度上是对已计数的引用的升级。
关于C++的一个优点是它不会强制垃圾收集。 我想纠正一个常见的误解:垃圾收集 神话 以某种方式消除泄漏。根据我的经验,调试他人编写的代码并试图发现最昂贵的逻辑泄漏的最可怕的噩梦是通过资源密集型主机应用程序使用诸如嵌入式Python之类的语言进行垃圾收集。 当谈论像GC这样的主题时,先有理论,然后有实践。从理论上讲,它很好,可以防止泄漏。然而,在理论层面上,每种语言都是美妙的,并且没有漏洞,因为从理论上讲,每个人都会写出完全正确的代码,并测试单个代码可能出错的每一个可能的情况。 垃圾收集加上不太理想的团队协作,导致了我们案例中最糟糕、最难调试的泄漏。 这个问题仍然与资源的所有权有关。当涉及持久性对象时,您必须在这里做出明确的设计决策,垃圾收集使您很容易认为自己没有。
有了一些资源,
因为开发者
然而,
没有垃圾收集,开发人员
有了垃圾收集,开发者
因此,垃圾收集不一定能够缓解逻辑资源泄漏。在不太理想的情况下,它可以使泄漏更容易被忽略并保留在软件中。开发人员在试图跟踪GC逻辑泄漏时可能会非常沮丧,他们只是告诉用户定期重启软件作为解决方法。它确实消除了悬空指针,在一个安全软件中,崩溃在任何情况下都是完全不可接受的,那么我更喜欢GC。但我经常在安全性不高但资源密集型、性能关键型产品中工作,在这些产品中,可以迅速修复的崩溃比一个非常隐蔽和神秘的无声错误更可取,而且资源泄漏在这些产品中并不是微不足道的错误。 在这两种情况下,我们谈论的都是不在堆栈上的持久对象,比如3D软件中的场景图,或者排字器中可用的视频剪辑,或者游戏世界中的敌人。当资源将其生命周期绑定到堆栈时,C++和任何其他GC语言都倾向于使管理资源正常。真正的困难在于引用其他资源的持久性资源。 在C或C++中,如果你不能清楚地指定谁拥有一个资源,并且当对它们的处理应该被释放(EX:响应于事件设置为NULL),则可以有由分段错误导致的悬空指针和崩溃。然而,在GC中,这种响亮、令人讨厌但往往容易发现的崩溃被交换为可能永远检测不到的无声资源泄漏。 |
|
|
Setu · 如何将元素从std::map移动到std::vector 1 年前 |
|
Konvt · 标准库中异常构造函数参数类型问题 1 年前 |
|
|
bourne · 关于操作员超载的澄清 1 年前 |