在C++中获取所有权和释放对象的语法准则

aby*_*s.7 7 c++ ownership

我想知道 - 有没有关于C++(非)成员函数语法的指导原则,这使我能够理解(如果可能的话,没有注释)其参数和返回值的所有权策略.所有权我的意思是,所有者负责销毁拥有的对象.

我区分了以下有关参数的规则:

  • 取得所有权
  • 不要拥有所有权
  • 分享

和关于返回值:

  • 发布('按值返回'在此组中)
  • 不释放
  • 分享

例如,通过引用传递对象不会占用它的所有权:

void func(object & obj) { ... }
Run Code Online (Sandbox Code Playgroud)

这些指南可能使用标准结构,如unique_ptr,shared_ptr等.如果没有这样的指导原则,那么也欢迎可能的语法误解的例子.

lar*_*moa 8

我不明白为什么使用智能指针是不够的.我想不出其他任何我不会归类为代码味道的东西.在原始指针上使用智能指针使得所有权和响应能力非常清晰:

  • auto_ptr/ unique_ptr- 单一所有者,所有权转移
  • shared_ptr - 多个所有者,所有权可能会转移
  • scoped_ptr - 单一所有者,所有权不能转让
  • weak_ptr- 观察者(但shared_ptr可能是从中创建的weak_ptr)

我认为这些足以清楚地表明责任,例如

void func(std::auto_ptr<Class> input) {...} // func() takes ownership of input
void func(std::shared_ptr<Class> input) {...} // func() and caller share ownership
std::auto_ptr<Class> func() {...} // caller takes ownership of returned value
std::shared_ptr<Class> func() {...} // func() and caller shares ownership of returned object
std::weak_ptr<Class> func() {...} // func() owns created object, but caller may observe it
Run Code Online (Sandbox Code Playgroud)

如你所述,在这个意义上,参考文献也很棒.请注意,是否需要使用某些自定义机制释放指针,shared_ptrunique_ptr支持自定义删除.auto_ptr没有这种能力.

注意!如果您使用的是C++ pre-11,则必须使用boost::shared_ptrboost:weak_ptr.

  • @Justin:如果它有自己的分配器,那么`unique_ptr`和`shared_ptr`可以被赋予自定义删除器来处理它.如果它有自己的引用计数方案,那么`boost :: intrusive_ptr`是一个不错的选择 - 它处理智能指针语义,你只需要处理引用计数本身. (3认同)

jus*_*tin 0

我只是在需要时使用此语法作为参数:

构造函数声明示例:

t_array(const t_ownership_policy::t_take& policy, THESpecialType* const arg);
Run Code Online (Sandbox Code Playgroud)

在调用站点使用:

t_array array(t_ownership_policy::Take, THESpecialTypeCreate(...));
Run Code Online (Sandbox Code Playgroud)

其中t_ownership_policy::t_take只是一个虚拟重载消歧器类型名。

在这个系统中,有多个策略,每个策略都有不同的类型。我喜欢每个策略都有唯一的类型,因为类型化枚举(例如)不那么容易支持初始化,并且很容易将不受支持的策略传递给函数或构造函数。“多态”策略可以减少符号数量,但这很痛苦,因为它将错误检测推到了运行时。

对于“返回”:

void func(t_container<t_type>& outValue);
Run Code Online (Sandbox Code Playgroud)

t_container您选择的指针容器类型在哪里。那么容器类型已经实现了必要的样板。这个容器可能类似于shared_ptr,或者您编写的一些专业化。

对于更复杂的类型,我经常使用如下语法:

void func(t_special_container& outValue) {
  ...
  outValue.take(ptr);
  - or -
  outValue.copy(ptr);
Run Code Online (Sandbox Code Playgroud)