问题标签 [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.

0 投票
11 回答
59065 浏览

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 。

用法:用于在只有循环维护共享引用计数时停止循环保留对象。

0 投票
12 回答
1798 浏览

c++ - 我如何*不*删除析构函数中的成员?

我希望我的类的析构函数删除整个对象,但其中一个成员除外,该成员在其他地方被删除。首先,这完全不合理吗?假设不是,我该怎么做?我认为创建一个带有空主体的析构函数会阻止所有成员被删除(因为析构函数不会做任何事情),但情况似乎并非如此。

0 投票
2 回答
631 浏览

c++ - 如何使用 Boost 库智能指针管理对象生命周期?

我需要使用 shared_ptr 和 weak_ptr 智能指针来解决一个场景。

两个线程,线程 1 和 2,正在使用一个名为 A 的共享对象。每个线程都有一个对该对象的引用。线程 1 决定删除对象 A,但同时线程 2 可能正在使用它。如果我使用 shared_ptr 在每个线程中保存对象 A 的引用,则该对象不会在正确的时间被删除。

我应该怎么做才能删除该对象,并防止同时使用该对象的其他线程出错?

0 投票
3 回答
22827 浏览

c++ - 为原始指针(如所有权语义)返回 unique_ptr 的坏习惯?

我编写了一个静态工厂方法,它返回一个从另一个数据对象填充的新 Foobar 对象。我最近一直沉迷于所有权语义,想知道我是否通过让这个工厂方法返回一个unique_ptr.

我的意图是告诉客户端代码他们拥有指针。如果没有智能指针,我只会返回Foobar*. 但是,我想强制删除此内存以避免潜在的错误,因此unique_ptr似乎是一个合适的解决方案。如果客户端想要延长指针的生命周期,他们只需.release()在获得unique_ptr.

我的问题分为两部分:

  1. 这种方法是否传达了正确的所有权语义?
  2. 这是返回unique_ptr而不是原始指针的“坏习惯”吗?
0 投票
1 回答
1999 浏览

qt - QAction 的所有权

将 QAction* 添加到负责删除 QAction* 对象的 QMenu 时?我在 QMenu 或 QAction 的文档中找不到它。

Qt Menus 示例不会删除它创建的任何操作,因此我假设 QMenu 拥有 QAction 。那是对的吗?

0 投票
3 回答
192 浏览

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:

我认为所有权需要在某个时候转移,但我不知道在哪里。

在此先感谢,盖伊

0 投票
2 回答
3637 浏览

c++ - 是否有适用于“把手”的适当“所有权在一个包中”?

除了指针之外,句柄还具有适当的语义。所以对我来说这样的例子(从零规则中提取):

unique_ptr用作句柄的“包中所有权”是一个不好的例子。首先,它利用句柄是指针类型的内部知识,并使用它来制作unique_ptr“不透明”句柄类型所基于的基本类型。

句柄可以是任何类型,它们可能是指针,可能是索引或谁知道。最重要的是,您手头(例如大多数 C API)是一个句柄及其资源释放函数。

是否存在适用于句柄语义的适当“包中所有权”?我的意思是,已经公开供一个人使用?

对我来说,unique_ptr等。人。不起作用,我必须对句柄类型什么做出不必要的假设,而我想要的只是通过不透明的句柄类型及其释放功能获得“包中的所有权”。

在句柄类型内部查看此信息以进行构造是没有意义的。是把手,应该没关系。

我将在另一个问题的 答案中引用另一个 SO 用户的感受:

创建一个特定的“智能指针”类,不会花很长时间。不要滥用图书馆课程。句柄语义与 C++ 指针的语义完全不同;一方面,取消引用 HANDLE 是没有意义的。

使用自定义智能句柄类的另一个原因 - NULL 并不总是意味着空句柄。有时是INVALID_HANDLE_VALUE,不一样。

免责声明:

这个问题重新制定并建立在这个问题之上:

0 投票
3 回答
603 浏览

c++ - 在 Delphi 中明确表达所有权

我主要是一名 C++ 程序员,而且我已经习惯于使用 , 等类模板std::unique_ptrstd::shared_ptr表达我的对象的所有权。Delphi 在其标准库中有类似的东西吗?在编写代码时,是否有任何表达对象所有权的最佳实践?

编辑:由于 C++11 成为标准,有两个轻量级帮助类,std::shared_ptrstd::unique_ptr.

如果我创建一个 type 的变量std::shared_ptr<int>,它代表一个指向具有共享所有权的 int 的指针:在底层是引用计数的,当引用计数达到零时,指针会自动释放。这种类型表达了一种“共享所有权”,其中许多对象在使用完资源后共同承担销毁资源的责任。

相反,std::unique_ptr表示单一所有权。当 unique_ptr 超出范围时,资源会自动释放。std::unique_ptr 不能被复制:一次只能有一个对象拥有该资源,并且只有一个对象负责清理该对象。

将这些轻量级类与指向 int 的裸指针进行对比,它可以表示共享所有权、唯一所有权,也可以只是对其他地方对象的引用!类型什么也没告诉你。

我的问题是:由于 Delphi 支持持有对对象的引用,是否有任何机制来明确声明“我是这个对象的唯一所有者,当我完成它时,我会释放它”,而不是“我只是保留一个为了与之交互而引用这个对象,但其他人会清理它”与“我与许多其他对象共享这个对象,最后拥有它的人可以清理它。”

我知道 Collections.Generics 有不同的集合,例如TListvs TObjectList,其中 TObjectList 将释放存储在其中的成员,但 TList 不会。您可以说 TObjectList “拥有”它的元素,而 TList 没有。这是我问题的本质,真的。在设计我自己的类时,有没有办法在语言中直接表达这些所有权问题?或者是否有开发人员常用的最佳实践/命名约定?

0 投票
2 回答
392 浏览

c++ - unique_ptr 所有权语义

也许我试图过于笼统。(下面的原始问题)具体来说,我对Depclass有一些依赖Foo。我也有一个类MockDep,并且正在定义一个类TestFoo。这是我尝试编写的构造函数:

AndFoo的构造函数看起来像:

mock_dep_TestFooas中声明MockDep* mock_dep_,并在as中声明。我怎样才能得到包含的地址?(因为上面的内容无效,因为nulls out 。)dep_Foounique_ptr<Dep> dep_mock_dep_dep_std::move(dep)dep


原帖:

我有一个类型的对象Foo,我要传递给另一个OtherObject声称拥有它的类型的对象,但作为指向它的基类的指针。但是,我想获取一个指向可以用来引用它的子对象的指针。我写了类似的东西:

但是,这似乎不起作用,因为似乎使稍后std::move(thing)返回的指针无效。thing.get()

我可以将Foo' 参数更改为 typeChild*而不是unique_ptr<Child>,但我更希望能够执行后者,因为它明确记录了所有权语义。

解决这个问题的最合适(或失败,不引人注目)的方法是什么?

编辑Foo并且OtherObject都意味着我正在定义其构造函数的类。

0 投票
2 回答
418 浏览

rust - Rust 中返回值的范围是什么?

当变量返回给调用者时,变量引用的数据会发生什么?当数据被破坏并且可能 Drop trait 被执行时?