python - C++ shared_ptr 与 Python 对象

标签 python c++ programming-languages shared-ptr

AFAIK,通常不鼓励使用 shared_ptr,因为不小心使用它们会导致潜在的错误(除非你对显着的好处和仔细检查的设计有很好的解释)。

另一方面,Python 对象似乎本质上是 shared_ptrs(ref_count 和垃圾收集)。

我想知道是什么让它们在 Python 中运行良好,但在 C++ 中可能存在危险。换句话说,Python 和 C++ 在处理 shared_ptr 方面有什么区别,这使得它们在 C++ 中不鼓励使用但在 Python 中不会引起类似问题?

我知道例如Python 会自动检测对象之间的循环,从而防止在 C++ 中可能导致悬空循环 shared_ptrs 的内存泄漏。

最佳答案

“我知道例如 Python 会自动检测循环”——这就是让它们很好地工作的原因,至少就与内存泄漏相关的“潜在错误”而言。

除此之外,与 Python 程序相比,C++ 程序更常在严格的性能约束下编写(IMO 是不同真实需求的组合,但在经验法则上存在一些相当虚假的差异,但那是另一回事)。我使用的大部分 Python 对象并不严格需要引用计数,它们只有一个所有者和一个 unique_ptr会很好(或者就此而言是类类型的数据成员)。在 C++ 中,它被认为(由编写您正在阅读的建议的人)值得利用性能优势和明确简化的设计。在 Python 中,它通常不被认为是一个问题,您为性能付出代价,并且您可以灵活地稍后决定是否共享它,而无需更改任何代码(我的意思是,除了获取比原始文件生命周期更长的其他引用之外)。

顺便说一句,在任何语言中,共享可变对象都有与之相关的“潜在错误”,如果您在不查看对象时忘记了哪些对象会发生变化或不会发生变化。我不仅仅是指竞争条件:即使在单线程程序中,您也需要意识到 C++ 谓词不应更改任何内容,并且您(通常)不能在迭代容器时对其进行变异。不过,我不认为这是 C++ 和 Python 之间的区别。相反,在某种程度上,您也应该对 Python 中的共享对象稍加警惕,并且当您对对象的引用激增时,至少要了解您为什么要这样做。

因此,转到您链接到的问题中的问题列表:

  • cyclic references -- 如前所述,Python 卷起袖子,找到它们并释放它们。由于语言的设计和特定用途的原因,在 C++ 中实现循环破坏垃圾收集相当困难,尽管并非不可能。
  • creating multiple unrelated shared_ptr s to the same object -- 在 Python 中不可能有类似的东西,因为引用计数器不对用户开放以搞乱。
  • Constructing an anonymous temporary shared pointer -- 在 Python 中不会出现,在 Python 中不存在内存泄漏的风险,因为没有“间隙”,其中对象存在,但如果它变得未引用,则还不会被收集。
  • Calling the get() function to get the raw pointer and use it after the pointed-to object goes out of scope -- 好吧,如果您正在编写 Python/C,但不是在纯 Python 中,您可能会搞砸。
  • Passing a reference of or a raw pointer to a shared_ptr should be dangerous too, since it won't increment the internal count -- 在 Python 中没有办法在没有语言处理引用计数的情况下添加引用。
  • we passed 'this' to some thread workers instead of 'shared_from_this' -- 换句话说,忘记创建 shared_ptr需要的时候。不能在 Python 中做到这一点。
  • most of the predicates you know and love from <functional> don't play nicely with shared_ptr -- Python refcounting 内置于运行时中(或者我想准确地说我应该说:垃圾收集内置于语言设计中)以至于没有任何库无法应对它。
  • Using shared_ptr for really small objects (like char short) could be an overhead -- Python 中存在问题,Python 程序员通常不会担心。如果你需要一个“原始类型”的数组,那么你可以使用 numpy以减少开销。有时 Python 程序内存不足,您需要对此做点什么,这就是生活;-)
  • Giving out a shared_ptr< T > to this inside a class definition is also dangerous. Use enabled_shared_from_this instead -- 这可能不是很明显,但这又是“不要为同一个对象创建多个不相关的 shared_ptr”。
  • You need to be careful when you use shared_ptr in multithread code -- 也可以在 Python 中创建竞争条件,这是“共享可变对象很棘手”的一部分。

  • 这主要是因为在 C++ 中你必须明确地做一些事情来获得 refcounting,如果你不要求它,你就不会得到它。这提供了多种出错机会,而 Python 不会提供给程序员,因为它只是为你做的。如果您使用 shared_ptr正确然后除了不与它合作的库的存在之外,这些问题也没有出现在 C++ 中。那些因为这些原因而谨慎使用它的人基本上是在说他们害怕他们会错误地使用它,或者至少比他们会滥用某些替代品更害怕。大部分 C++ 编程都在相互交换不同的潜在错误,直到您提出一个您认为自己有能力执行的设计。此外,它还将“不要为不需要的东西付费”作为设计理念。在这两个因素之间,如果没有很好的解释、显着的好处和仔细检查的设计,你就不会做任何事情。 shared_ptr没有什么不同;-)

    关于python - C++ shared_ptr 与 Python 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32362884/

    相关文章:

    python - 合并来自不同文件夹的图像并将其存储到另一个文件夹

    python - 如果您的 sys.path 使用相对目录,python 会在哪里查找?

    c++ - 计算负数的模数

    c - 将节点放入不应该存在的解析树中

    language-agnostic - 为什么不同的算子有不同的结合性?

    python - 带有特定 python 库的 spark-submit

    python - 理解 python 中的子类

    c++ - 在 C++ 中创建一个执行 Matlab 操作 [z;z] 的函数,其中 z 是矩阵或 vector

    c++ - 空的 variardic 枚举包——它们是否使两个函数不同?

    language-agnostic - 有通用的语言模型吗?