如何记录所有权? [英] How to document ownership?

查看:90
本文介绍了如何记录所有权?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到记录(在代码和

注释中)二级包含对象的所有权的最佳方式。这是我的

当前状态,我很感激反馈:


案例1:当用对象创建辅助对象时

并与对象一起消亡。


解决方案:将辅助对象保留为堆栈变量,并且

deallocation成为无问题。


例如:


班级人物

{



私人:

性别性别_;

};


案例2:存在辅助对象时在其他地方(即由其他人拥有

)但是由班级引用。


解决方案:将辅助对象保留为(可能是const)引用。

通过构造函数或setter方法传递引用。

引用表明它存在于其他地方并且类

永远不应该删除它。 br />

例如:


class Person {

public:

Person(Person&妈妈);

private:

Person& mother_;

};


案例3:与案例2类似,但次要对象可能为0.


解决方案:将辅助对象保存为(可能是const / const)指针。

传递指针throgh构造函数或setter方法但是文档

所有权在其他地方都有。


示例:


class Person {

public:

void setSpouse(Person *配偶);

私人:

人*配偶_;

};


案例4 :一个辅助对象由客户端创建并传递给成为其所有者的
a类。


解决方案:将辅助对象保持为内部指针,并且

将它作为指针传递(即使它不能为0)。可能是文件

事实上,辅助对象现在由对象拥有,并且

还记录了前提条件声明它不能为空。


例如:


class Person {

public:

void setHairstyle(Hairstyle * hairstyle);

私人:

发型*发型_;

};

人物::〜人物()

{

删除发型_;

}


目前我在案例3遇到问题需要记录<拥有该对象的
(通过评论)和案例4我通过指针传递一个对象

,即使它不能为0.我可以在技术上通过

它作为参考但是通过将其作为指针传递我明确指出

它是*不是*对其他地方存在的对象的引用。

它然后变得(更明)所有权在哪里。


有什么想法吗?


谢谢!

I am trying to find the best way of documenting (in code and
comments) ownership of secondary contained objects. This is my
current status, and I would appreciate feedback on it:

Case 1: When the secondary object is created with the object
and dies with the object.

Solution: Keep the secondary object as a stack variable, and
deallocation becomes a no-issue.

Example:

class Person
{
:
private:
Gender gender_;
};


Case 2: When a secondary object exists somewhere else (i.e. is owned
by someone else) but is referred to by the class.

Solution: Keep secondary object as a (possibly const) reference.
Pass reference through constructor or setter method.
The reference indicate that it exists somewhere else and the class
should never delete it.

Example:

class Person {
public:
Person(Person& mother);
private:
Person& mother_;
};

Case 3: Like case 2, but where the secondary object might be 0.

Solution: Keep secondary object as a (possibly const/const) pointer.
Pass pointer throgh constructor or setter method BUT DOCUMENT THE
FACT THAT OWNERSHIP IS ELSEWHERE.

Example:

class Person {
public:
void setSpouse(Person* spouse);
private:
Person* spouse_;
};

Case 4: A secondary object is created by a client and passed into
a class who becomes its owner.

Solution: Keep secondary object as a pointer internally and also
pass it as a pointer (even when it cannot be 0). Possibly document
the fact that the secondary object is now owned by the object, and
also document that it cannot be null by a precondition assert.

Example:

class Person {
public:
void setHairstyle(Hairstyle* hairstyle);
private:
Hairstyle* hairstyle_;
};
Person::~Person()
{
delete hairstyle_;
}

Currently I have trouble with case 3 where I need to document
(by comments) who owns the object, and case 4 where I pass an object
through a pointer even when it cannot be 0. I could technically pass
it as a reference but by passing it as a pointer I explicitly indicate
that it is *not* a reference to an object that exists elsewhere.
It then becomes (more) obvious where ownership is.

Any thoughts?

Thanks!

推荐答案

你好


雅各布写道:
Hi

Jacob wrote:
我正在努力找到最好的记录方式(代码中)和
评论)二级包含对象的所有权。这是我现在的状态,我会很感激反馈:
[...很多原始指针......]有什么想法吗?
I am trying to find the best way of documenting (in code and
comments) ownership of secondary contained objects. This is my
current status, and I would appreciate feedback on it: [... lots of raw pointers ...] Any thoughts?




你应该考虑使用std :: auto_ptr。

你也可以看一下boost智能指针

http://www.boost.org/libs/smart_ptr/smart_ptr.htm


Markus



You should consider using std::auto_ptr.
You might also have a look at the boost smart pointers
( http://www.boost.org/libs/smart_ptr/smart_ptr.htm ).

Markus





Jacob写道:


Jacob wrote:
我正在尝试找到记录(在代码和
注释中)二级包含对象的所有权的最佳方法。这是我目前的状态,我很感激反馈:


这并不难。您只需将成员变量注释为拥有即可。或者

持有。

案例1:当用对象创建辅助对象并且与对象一起死亡时。


[snip]例如:

类人物
{

私人:
性别性别_;
};


在这种情况下,你甚至不必记录''gender_''是拥有的

,因为它不可能。

案例2:当一个辅助对象存在于其他地方时(即由其他人拥有)但是由该类引用。


这是事情变得有趣的地方。当你给一个要保持的类的外部对象

时,总是将它作为指针传递:


[snip] class Person {
public :
人(人与母);
私人:
人与人mother_;
};


class Person {

Person * d_mother_p; //这个人的母亲(持有)


公众:

人(人*母亲);

};


将''mother_p''存储为指针的主要原因(注意''_p''

后缀)是表示它是举行(尽管它可能是拥有的,因为你需要记录这个事实)。由于''mother''存储为

指针,因此为了对称原因,你应该将它作为指针传递,

并且还要记录给客户的读者可能会持有参数

的代码(但绝对不会被复制)。


例如,在下面的代码片段中


酒吧吧;

Foo foo(酒吧);

// ...


目前尚不清楚

''foo''持有并且不拥有(通过复制)'bar''。因此,很难发现涉及外部对象bar的过早删除的错误。但是,


吧台酒吧;

Foo foo(& bar);

// ......


清楚地暗示了酒吧意味着比'foo'更长的可能性。


你的例子特别有趣,因为你的构造函数<由''母亲'参数化的
实际上表示为复制构造函数。

我不知道这是否是故意的,但它肯定会导致

一些有趣的错误。

案例3:与案例2类似,但次要对象可能为0.


[snip]示例:

班级人员{
公众:
void setSpouse(人*配偶);
私人:
人* spouse_;
};


Hapilly,这与案例2相同:


class Person {

Person * d_spouse_p; //这个人的配偶(持有)

public:

void setSpouse(Person * spouse);

//设置这个人配偶指定''配偶''。

};


''配偶''可能为零的事实是一个实现细节你不需要在界面中记录
。但是,您可能希望

externalize''spouse_p''在这种情况下您可以添加


const Person * spouse()const;

//返回此人的配偶(如果有的话);否则

//返回0.


''spouse_p''可以为空并不重要。重要的是

您的访问者可以*返回*空指针。

案例4:辅助对象由客户创建并传递到
类谁成为它的主人。


[snip]示例:

类人员{
公众:
void setHairstyle(发型*发型);
私人:
发型*发型_;
};

人:〜人()
{
删除发型_;
}
I am trying to find the best way of documenting (in code and
comments) ownership of secondary contained objects. This is my
current status, and I would appreciate feedback on it:
This is not hard. You simply comment the member variable as "owned" or
"held".
Case 1: When the secondary object is created with the object
and dies with the object.
[snip] Example:

class Person
{
:
private:
Gender gender_;
};
In this case, you don''t even have to document that ''gender_'' is "owned"
because it cannot be otherwise.
Case 2: When a secondary object exists somewhere else (i.e. is owned
by someone else) but is referred to by the class.
This is where things get interesting. When you give an external object
to a class to hold, always pass it as a pointer:

[snip] class Person {
public:
Person(Person& mother);
private:
Person& mother_;
};
class Person {
Person *d_mother_p; // this person''s mother (held)

public:
Person(Person *mother);
};

The main reason why you store ''mother_p'' as a pointer (note the ''_p''
suffix) is to denote that it is held (although it may be owned which is
why you need to document this fact). Since ''mother'' is stored as a
pointer, you should pass it as a pointer both for reasons of symmetry,
and also to document to the reader of client code that the argument
might be held (but is definitely not copied).

For example, in the following snippet

Bar bar;
Foo foo(bar);
//...

it is not clear that ''bar'' is held and not owned (via copying) by
''foo''. Hence, it is difficult to spot bugs involving the premature
deletion of the external object ''bar''. However,

Bar bar;
Foo foo(&bar);
//...

clearly hints at the likelyhood that ''bar'' is meant to outlive ''foo''.

Your example is especially interesting because your constructor
parameterized by ''mother'' is actually expressed as a copy constructor.
I don''t know if this was deliberate, but it could certainly lead to
some interesting bugs.
Case 3: Like case 2, but where the secondary object might be 0.
[snip] Example:

class Person {
public:
void setSpouse(Person* spouse);
private:
Person* spouse_;
};
Hapilly, this is the same as Case 2:

class Person {
Person *d_spouse_p; // this person''s spouse (held)
public:
void setSpouse(Person *spouse);
// Set this person''s spouse to the specified ''spouse''.
};

The fact that ''spouse'' may be zero is an implementation detail that you
don''t need to document in the interface. However, you might want to
externalize ''spouse_p'' in which case you may add

const Person *spouse() const;
// Return this person''s spouse, if one exists; otherwise
// return 0.

It''s not important that ''spouse_p'' can be null. It is important that
your accessor may *return* a null pointer.
Case 4: A secondary object is created by a client and passed into
a class who becomes its owner.
[snip] Example:

class Person {
public:
void setHairstyle(Hairstyle* hairstyle);
private:
Hairstyle* hairstyle_;
};
Person::~Person()
{
delete hairstyle_;
}




这个案例也与案例2相同:


class Person {

Hairstyle * d_hairstyle_p ; //这个人的发型(拥有)

公共:

void setHairstyle(发型*发型);

//设置这个人'发型到指定的

''发型''。

};


但是,这也不是很好的例子。实际上有两个外部对象可能变为拥有的情况。由''人''。在

这两种情况下,所有权点与调用者中两个对象的相对寿命相关。


第一种情况涉及价值语义对象(那些定义了复制

构造函数和赋值运算符)。在这种情况下,人可以bb拥有通过复制其值来创建外部对象:


class Person {

Hairstyle d_haristyle;

public:

void setHairstyle(const发型和发型)

{d_hairstyle =发型; }

};


按惯例传递const引用是指示

参数可能被复制其他对象,并且调用者可以自由地在相对于另一个对象的任何点销毁参数对象:


Foo foo;

{

酒吧;

foo.setBar(bar);

}

foo.action (); //涉及''bar''


第二种情况涉及将动态

分配资源的所有权放弃到另一个对象。但是,在这种情况下,我会建议(就像其他人在这个帖子中所做的那样)使用托管的

指针,例如''std :: auto_ptr''或者共享指针。但是,请小心地通过* modifiable *参考传递这些:


void setConnectionPool(std :: auto_ptr< ConnectionPool>& pool);


setConnectionPool的实现可以通过在''auto_ptr'之间进行分配来获得''pool''

的所有权,或者可以选择委托

将''池''的所有权转让给另一个对象。


这种技术的实用性在你获得时更加明显

从除new / delete之外的分配器分配动态资源。在

这种情况​​下,您可以将对象和分配器捆绑在一个托管的

指针中,这样新的所有者就不需要知道

用于分配(和解除分配)对象的特定分配器类型。

(遗憾的是,''auto_ptr''目前不支持这种接口。)


HTH,/ david



This case is also the same as Case 2:

class Person {
Hairstyle *d_hairstyle_p; // this person''s hairstyle (owned)
public:
void setHairstyle(Hairstyle *hairstyle);
// Set this person''s hairstyle to the specified
''hairstyle''.
};

However, this too is not a very good example. There are really two
cases where an external object may become "owned" by a ''Person''. In
both cases, the point of ownership relates more than anything to the
relative lifespan of the two objects in the caller.

The first case involves value-semantic objects (those which define copy
constructors and assignment operators). In this case, a ''Person'' may
"own" an external object by copying its value:

class Person {
Hairstyle d_haristyle;
public:
void setHairstyle(const Hairstyle& hairstyle)
{ d_hairstyle = hairstyle; }
};

Passing by const reference is, by convention, an indication that the
argument may be copied by the other object, and the caller is free to
destroy the argument object at any point relative to the other object:

Foo foo;
{
Bar bar;
foo.setBar(bar);
}
foo.action(); // involves ''bar''

The second case involves relinquishing ownership of a dynamically
allocated resource to another object. However, in this case I would
suggest (as someone else did in this thread) the use of managed
pointers such as ''std::auto_ptr'' or a shared pointer. However, be
careful to pass these by *modifiable* reference:

void setConnectionPool(std::auto_ptr<ConnectionPool>& pool);

The implementation of ''setConnectionPool'' may take ownership of ''pool''
by making an assignment between ''auto_ptr''s, or may chose to delegate
ownership of ''pool'' to yet another object.

The usefulness of this technique becomes more apparent when you
allocate dynamic resources from an allocator other than new/delete. In
this case, you can bundle the object and the allocator in a managed
pointer so that the new owner does not need to be aware of the
particular allocator type used to allocate (and deallocate) the object.
(Sadly, ''auto_ptr'' does not currently support this kind of interface.)

HTH, /david




da ******** @ warpmail.net 写道:


da********@warpmail.net wrote:
存储''mother_p''的主要原因是一个指针(注意''_p''
后缀)
The main reason why you store ''mother_p'' as a pointer (note the ''_p''
suffix)




是的,我确实注意到了,非常难看,为什么你认为坚持这个? />
最后的憎恶是个好主意?



Yes I did note it, very ugly, why do you think that sticking that
abomination on the end is a good idea ?


这篇关于如何记录所有权?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆