473,461 Members | 1,491 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

How to document ownership?

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!
Jul 23 '05 #1
11 1851
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?


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

Jul 23 '05 #2


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:
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_;
}


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

Jul 23 '05 #3
Geo


da********@warpmail.net wrote:
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 ?

Jul 23 '05 #4


Geo wrote:
da********@warpmail.net wrote:
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 ?


So I can tell which variables are pointers and which are not at a
glance. It's just a convention. Take it or leave it. /david

Jul 23 '05 #5
da********@warpmail.net wrote:
So I can tell which variables are pointers and which are not at a
glance. It's just a convention. Take it or leave it. /david


Leave it! It is a misconception to associate type with
modelling concepts. It's equivalent to:

int nTableInteger;
double temperatureDouble;

Only occationally I want to emphasize a name with a type;
like this:

string temperatureString = ...;
double temperature = temperatureString.toDouble();


Jul 23 '05 #6
Markus Moll wrote:
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 ).


Though smart pointers may help you manage your
memory, they will (I guess; I have limited experience
in the field) fail to document ownership.

It might be argued that it technically might not be
needed, but from a modelling point of view I
still find the raw counterparts valuable.
Jul 23 '05 #7
da********@warpmail.net wrote:

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:

This is not hard. You simply comment the member variable as "owned" or
"held".


I like to document as much as possible with the syntax
of the language. Relaying on comment conventions like this
is asking for trouble down the road.

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:


I see no reason why this should not be a reference.
This is after all the classical situation where you
do use a reference, isn't it?

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:


You claim that parameters passed as const reference should
always be copied at the destination? That is not my current
practice, could you elaborate?

public:
void setMother(const Person& mother)
{
mother_ = mother;
}

private:
Person mother_;
I'd rather keep the private variable as a reference, but it is
of course then assumed that the object (the mother) outlive
the specific instance.
Jul 23 '05 #8
Jacob wrote:
Markus Moll wrote:
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 ).

Though smart pointers may help you manage your
memory, they will (I guess; I have limited experience
in the field) fail to document ownership.

What do you mean by ownership? If you mean responsibility
for deallocating the object, smart pointers do that.
Everybody knows that's what smart pointers do. You can't
get more documented than that.

--
Joe Seigh

When you get lemons, you make lemonade.
When you get hardware, you make software.
Jul 23 '05 #9


Jacob wrote:
da********@warpmail.net wrote:
So I can tell which variables are pointers and which are not at a
glance. It's just a convention. Take it or leave it. /david


Leave it! It is a misconception to associate type with
modelling concepts. It's equivalent to:

int nTableInteger;
double temperatureDouble;


I agree that associating a type with a concept (via a name) is not a
good idea, but that is not what I'm advocating. The '_p' convention
just says "this is a pointer", regardless of a particular type. While
it may seem redundant to you as the author, it is very useful to other
people who are reading the code.

In any case, this convention was...strongly suggested to me by my
current management, and I've grown to appreciate it enormously. YMMV.
/david

Jul 23 '05 #10


Jacob wrote:
da********@warpmail.net wrote:

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:

This is not hard. You simply comment the member variable as "owned" or
"held".


I like to document as much as possible with the syntax
of the language. Relaying on comment conventions like this
is asking for trouble down the road.


Please explain.
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:


I see no reason why this should not be a reference.
This is after all the classical situation where you
do use a reference, isn't it?


The data method is a pointer because the parameter is a pointer. The
parameter is a pointer because you want to provide a hint to the reader
of the client code that the lifespan of the parameter must (may have
to) outlast that of the target object.

I would argue that the "classical" situation where you use a reference
is passing or returning a constant reference.
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:
You claim that parameters passed as const reference should
always be copied at the destination? That is not my current
practice, could you elaborate?


No, I'm saying that the *may* be copied. Certainly you cannot copy
every object you pass as const reference. But the point is that objcet
you pass as pointers are never copied, and that is why you pass (and
store) parameters that are "held" as pointers.
public:
void setMother(const Person& mother)
{
mother_ = mother;
}

private:
Person mother_;
I'd rather keep the private variable as a reference, but it is
of course then assumed that the object (the mother) outlive
the specific instance.


There is no justification for this assumption. In fact, when your
arguments are value-semantic objects, the expectation is exactly the
opposite: the object will either be copied or used only within the
context of the function call. However,

void setMother(const Person *mother);

certainly makes you think twice about the expected lifespan of 'mother'
relative to the 'Person'. Re-enforcing this contract in the function's
documentation can only help the situation. /david

Jul 23 '05 #11
Hello,
You can think up using reference count, where the object takes the ownership
it self and itself when it goes out of scope.
For more info on Reference count see "More Effective C++" By Scote Mayer
"Joe Seigh" <js*******@xemaps.com> wrote in message
news:Vc********************@comcast.com...
Jacob wrote:
Markus Moll wrote:
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 ).

Though smart pointers may help you manage your
memory, they will (I guess; I have limited experience
in the field) fail to document ownership.

What do you mean by ownership? If you mean responsibility
for deallocating the object, smart pointers do that.
Everybody knows that's what smart pointers do. You can't
get more documented than that.

--
Joe Seigh

When you get lemons, you make lemonade.
When you get hardware, you make software.

Jul 23 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Ryan | last post by:
We have a DTS package developed on our development PC's (SQL 7). It runs fine. When we schedule it on the server (SQL 7), it fails. We have been able to find that this is a known issue down to the...
4
by: tarmat | last post by:
I've been using code such as the following, whereby I call the constructor of a class with an object allocated on the heap. The class is responsible for tidying up the memory. class Base{};...
14
by: Howard | last post by:
Hi, I recently had a problem where I decided to store objects in a vector. (Previously, I had always stored pointers in vectors). Well, naturally, when storing an object in a vector, using...
2
by: Benden Ziyade | last post by:
Hello; I want to write a C program that check file ownership in /bin directory(ls, mkdir...). But I don't know how I start. I'm happy with your helping.
9
by: Andrew | last post by:
Apologies for the double-post.. I'm new, just getting used to this.. and should have posted this way in the first place.. How does one go about taking ownership of a registry key using C# & .NET...
1
by: ShaiH | last post by:
When I create a file from a simple command line application written in C# the file ownership given to the newly created file is of administrators group although I am running this application in my...
14
by: Alf P. Steinbach | last post by:
Not yet perfect, but: http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01.pdf http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01_examples.zip To access the table of...
4
by: garethfx | last post by:
I've been handed a little task of developing a document control system in ms access. Its require that the "documents" will be in ms word and also pdf formats. Never having done this before has...
0
by: digz | last post by:
In the code below , a simplified version I need to pass a smart pointer to function f which I control .I cannot use std::auto_ptr as a parameter to f because it releases ownership on copy...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.