我想知道 - 是否有关于C ++(非)成员函数语法的指导,这使我能够理解(如果可能的话,没有注释)其参数和返回值的所有权策略。根据所有权,我的意思是,所有者负责销毁拥有的对象。
我区分了以下有关参数的规则:
和关于返回值:
例如,通过引用传递对象不会拥有它的所有权:
void func(object & obj) { ... }
此类指南可能使用标准结构,如unique_ptr,shared_ptr等。如果没有这样的指导原则,那么也欢迎可能存在语法误解的示例。
答案 0 :(得分:8)
我看不出为什么使用智能指针是不够的。我想不出任何我不会归类为code smell的东西。在原始指针上使用智能指针使得所有权和响应能力非常清晰:
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
正如您所提到的,从这个意义上来说,参考文献也很棒。请注意,如果需要使用某种自定义机制释放指针,shared_ptr
和unique_ptr
支持自定义删除。 auto_ptr
没有此功能。
请注意!如果您使用的是C ++ pre-11,则必须使用boost::shared_ptr
和boost:weak_ptr
。
答案 1 :(得分:0)
我只是在需要的地方使用这种语法:
示例构造函数声明:
t_array(const t_ownership_policy::t_take& policy, THESpecialType* const arg);
在呼叫现场使用:
t_array array(t_ownership_policy::Take, THESpecialTypeCreate(...));
其中t_ownership_policy::t_take
只是一个虚拟重载消歧器类型名称。
在此系统中,有多个策略,每个策略都有不同的类型。我赞成每个策略的唯一类型,因为类型化枚举(例如)不容易支持初始化,并且将不受支持的策略传递给函数或构造函数太容易了。 “多态”策略可以减少符号数量,但这很痛苦,因为它会将错误检测推送到运行时。
'返回':
void func(t_container<t_type>& outValue);
其中t_container
是您选择的指针容器类型。然后容器类型已经实现了必要的样板。这个容器可能类似于shared_ptr
,或者你写过的一些专业化。
对于更复杂的类型,我经常使用这样的语法:
void func(t_special_container& outValue) {
...
outValue.take(ptr);
- or -
outValue.copy(ptr);
答案 2 :(得分:0)
如果我了解你,那么Boost call_traits可能就是你想要的:
示例(从文档中复制):
template <class T>
struct contained
{
// define our typedefs first, arrays are stored by value
// so value_type is not the same as result_type:
typedef typename boost::call_traits<T>::param_type param_type;
typedef typename boost::call_traits<T>::reference reference;
typedef typename boost::call_traits<T>::const_reference const_reference;
typedef T value_type;
typedef typename boost::call_traits<T>::value_type result_type;
// stored value:
value_type v_;
// constructors:
contained() {}
contained(param_type p) : v_(p){}
// return byval:
result_type value() { return v_; }
// return by_ref:
reference get() { return v_; }
const_reference const_get()const { return v_; }
// pass value:
void call(param_type p){}
};
比param_type
,reference_type
和return_type
更清楚地表明其含义。