问题标签 [ownership-semantics]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 智能指针:谁拥有对象?
C++ 是关于内存所有权的——也就是所有权语义。
一块动态分配的内存的所有者有责任释放该内存。所以问题真的变成了谁拥有记忆。
在 C++ 中,所有权由包装在内部的原始指针的类型记录,因此在一个好的(IMO)C++ 程序中,很少(很少,不是从不)看到传递的原始指针(因为原始指针没有推断的所有权,因此我们可以不知道谁拥有内存,因此如果不仔细阅读文档,您就无法知道谁负责所有权)。
相反,很少看到原始指针存储在一个类中,每个原始指针都存储在其自己的智能指针包装器中。(注意:如果您不拥有一个对象,则不应存储它,因为您不知道它何时会超出范围并被销毁。)
所以问题:
- 人们遇到了什么类型的所有权语义?
- 使用哪些标准类来实现这些语义?
- 你觉得它们在什么情况下有用?
让我们为每个答案保留一种语义所有权,以便可以单独对它们进行上下投票。
概括:
从概念上讲,智能指针很简单,简单的实现也很容易。我见过许多尝试的实现,但它们总是以某种方式被破坏,这对于随意使用和示例来说并不明显。因此,我建议始终使用库中经过良好测试的智能指针,而不是自己滚动。std::auto_ptr
或者 Boost 智能指针之一似乎可以满足我的所有需求。
std::auto_ptr<T>
:
单身人士拥有该物品。允许转让所有权。
用法:这允许您定义显示所有权显式转移的接口。
boost::scoped_ptr<T>
单身人士拥有该物品。不允许转让所有权。
用法:用于显示明确的所有权。对象将被析构函数或显式重置时销毁。
boost::shared_ptr<T>
( std::tr1::shared_ptr<T>
)
多重所有权。这是一个简单的引用计数指针。当引用计数达到零时,对象被销毁。
用法:当一个对象可以有多个生命周期无法在编译时确定时。
boost::weak_ptr<T>
:
shared_ptr<T>
在可能发生指针循环的情况下使用 with 。
用法:用于在只有循环维护共享引用计数时停止循环保留对象。
c++ - 我如何*不*删除析构函数中的成员?
我希望我的类的析构函数删除整个对象,但其中一个成员除外,该成员在其他地方被删除。首先,这完全不合理吗?假设不是,我该怎么做?我认为创建一个带有空主体的析构函数会阻止所有成员被删除(因为析构函数不会做任何事情),但情况似乎并非如此。
c++ - 如何使用 Boost 库智能指针管理对象生命周期?
我需要使用 shared_ptr 和 weak_ptr 智能指针来解决一个场景。
两个线程,线程 1 和 2,正在使用一个名为 A 的共享对象。每个线程都有一个对该对象的引用。线程 1 决定删除对象 A,但同时线程 2 可能正在使用它。如果我使用 shared_ptr 在每个线程中保存对象 A 的引用,则该对象不会在正确的时间被删除。
我应该怎么做才能删除该对象,并防止同时使用该对象的其他线程出错?
c++ - 为原始指针(如所有权语义)返回 unique_ptr 的坏习惯?
我编写了一个静态工厂方法,它返回一个从另一个数据对象填充的新 Foobar 对象。我最近一直沉迷于所有权语义,想知道我是否通过让这个工厂方法返回一个unique_ptr
.
我的意图是告诉客户端代码他们拥有指针。如果没有智能指针,我只会返回Foobar*
. 但是,我想强制删除此内存以避免潜在的错误,因此unique_ptr
似乎是一个合适的解决方案。如果客户端想要延长指针的生命周期,他们只需.release()
在获得unique_ptr
.
我的问题分为两部分:
- 这种方法是否传达了正确的所有权语义?
- 这是返回
unique_ptr
而不是原始指针的“坏习惯”吗?
qt - QAction 的所有权
将 QAction* 添加到负责删除 QAction* 对象的 QMenu 时?我在 QMenu 或 QAction 的文档中找不到它。
Qt Menus 示例不会删除它创建的任何操作,因此我假设 QMenu 拥有 QAction 。那是对的吗?
c++ - 我的新 Unique_ptrs 的所有权?
根据我最近在一次工作面试中的建议,我被建议研究 C++11 的 unique_ptr 功能,作为自动垃圾收集的一种手段。所以我正在使用一个较旧的项目,并用 unique_ptrs 替换指向使用“new”关键字创建的对象的原始指针。但是,我认为我已经解决了所有权问题。
在我的 mainclass.cpp(发布在下面)中,请将您的注意力转移到 init 函数和 3 个 unique_ptrs 到我创建的新实例化对象上。命名为“bg”、“bg2”和“theGrid”。(它们下面被注释掉的声明是它们以前是如何完成的,切换回这个方法,程序运行得很好。)
但是,使用 unique_ptrs,函数 void display() 中的行:
产生访问冲突。这也是序列中第一次取消引用任何指向的对象,这让我相信 unique_ptr 的所有权已经在某个地方丢失了。但是,unique_ptrs 本身永远不会传递到另一个函数或容器中,并且仍然在 mainclass.cpp 的范围内,因此我没有看到任何机会使用 std::move(theGrid) 来将所有权转移到它需要的地方成为。
主类.cpp:
我认为所有权需要在某个时候转移,但我不知道在哪里。
在此先感谢,盖伊
c++ - 是否有适用于“把手”的适当“所有权在一个包中”?
除了指针之外,句柄还具有适当的语义。所以对我来说这样的例子(从零规则中提取):
unique_ptr
用作句柄的“包中所有权”是一个不好的例子。首先,它利用句柄是指针类型的内部知识,并使用它来制作unique_ptr
“不透明”句柄类型所基于的基本类型。
句柄可以是任何类型,它们可能是指针,可能是索引或谁知道。最重要的是,您手头(例如大多数 C API)是一个句柄及其资源释放函数。
是否存在适用于句柄语义的适当“包中所有权”?我的意思是,已经公开供一个人使用?
对我来说,unique_ptr
等。人。不起作用,我必须对句柄类型是什么做出不必要的假设,而我想要的只是通过不透明的句柄类型及其释放功能获得“包中的所有权”。
在句柄类型内部查看此信息以进行构造是没有意义的。是把手,应该没关系。
创建一个特定的“智能指针”类,不会花很长时间。不要滥用图书馆课程。句柄语义与 C++ 指针的语义完全不同;一方面,取消引用 HANDLE 是没有意义的。
使用自定义智能句柄类的另一个原因 - NULL 并不总是意味着空句柄。有时是INVALID_HANDLE_VALUE,不一样。
免责声明:
这个问题重新制定并建立在这个问题之上:
c++ - 在 Delphi 中明确表达所有权
我主要是一名 C++ 程序员,而且我已经习惯于使用 , 等类模板std::unique_ptr
来std::shared_ptr
表达我的对象的所有权。Delphi 在其标准库中有类似的东西吗?在编写代码时,是否有任何表达对象所有权的最佳实践?
编辑:由于 C++11 成为标准,有两个轻量级帮助类,std::shared_ptr
和std::unique_ptr
.
如果我创建一个 type 的变量std::shared_ptr<int>
,它代表一个指向具有共享所有权的 int 的指针:在底层是引用计数的,当引用计数达到零时,指针会自动释放。这种类型表达了一种“共享所有权”,其中许多对象在使用完资源后共同承担销毁资源的责任。
相反,std::unique_ptr
表示单一所有权。当 unique_ptr 超出范围时,资源会自动释放。std::unique_ptr 不能被复制:一次只能有一个对象拥有该资源,并且只有一个对象负责清理该对象。
将这些轻量级类与指向 int 的裸指针进行对比,它可以表示共享所有权、唯一所有权,也可以只是对其他地方对象的引用!类型什么也没告诉你。
我的问题是:由于 Delphi 支持持有对对象的引用,是否有任何机制来明确声明“我是这个对象的唯一所有者,当我完成它时,我会释放它”,而不是“我只是保留一个为了与之交互而引用这个对象,但其他人会清理它”与“我与许多其他对象共享这个对象,最后拥有它的人可以清理它。”
我知道 Collections.Generics 有不同的集合,例如TList
vs TObjectList
,其中 TObjectList 将释放存储在其中的成员,但 TList 不会。您可以说 TObjectList “拥有”它的元素,而 TList 没有。这是我问题的本质,真的。在设计我自己的类时,有没有办法在语言中直接表达这些所有权问题?或者是否有开发人员常用的最佳实践/命名约定?
c++ - unique_ptr 所有权语义
也许我试图过于笼统。(下面的原始问题)具体来说,我对Dep
class有一些依赖Foo
。我也有一个类MockDep
,并且正在定义一个类TestFoo
。这是我尝试编写的构造函数:
AndFoo
的构造函数看起来像:
mock_dep_
在TestFoo
as中声明MockDep* mock_dep_
,并在as中声明。我怎样才能得到包含的地址?(因为上面的内容无效,因为nulls out 。)dep_
Foo
unique_ptr<Dep> dep_
mock_dep_
dep_
std::move(dep)
dep
原帖:
我有一个类型的对象Foo
,我要传递给另一个OtherObject
声称拥有它的类型的对象,但作为指向它的基类的指针。但是,我想获取一个指向可以用来引用它的子对象的指针。我写了类似的东西:
但是,这似乎不起作用,因为似乎使稍后std::move(thing)
返回的指针无效。thing.get()
我可以将Foo
' 参数更改为 typeChild*
而不是unique_ptr<Child>
,但我更希望能够执行后者,因为它明确记录了所有权语义。
解决这个问题的最合适(或失败,不引人注目)的方法是什么?
编辑:Foo
并且OtherObject
都意味着我正在定义其构造函数的类。
rust - Rust 中返回值的范围是什么?
当变量返回给调用者时,变量引用的数据会发生什么?当数据被破坏并且可能 Drop trait 被执行时?