471,612 Members | 2,455 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,612 software developers and data experts.

References, AddressOf and Object management

Am I correct in think that you can't re-assign a reference to a different
object? If so, what should happen here:

struct A
{
DoSomeThing();
};

A& GetNextA();

while (1)
{
A& a = GetNextA();

a.DoSomeThing();
}

Does reference 'a' only get assigned first time around the loop and,
thereafter, object 'a' gets assigned to the next 'A'... or is 'a' connected
to a different 'A' every time around the loop? What about this:

while (1)
{
{
A& a = GetNextA();

a.DoSomeThing();
}
}

Surely, 'a' would now be different every time around the loop (because the
scope of 'a' ends before looping?

On a related note, is it possible to prevent a reference to a class
instance? Similarly, is it possible to prevent the address of an instance
from being taken?

What I'm looking for is a way to implement a 'Reference<T>' class. In other
words, some kind of class like a smart-pointer except that the 'Reference'
is the only way to access the object to which it refers. I want to prevent
'address-of' and references and use the 'Reference' as a means to manage
object life-time.

Any insight or links to good articles will be very much appreciated.

Regards
Tim
Jul 22 '05 #1
29 1791

"Tim Clacy" <no*******@nospamphaseone.nospamdk> wrote in message news:40*********************@dread11.news.tele.dk. ..
while (1)
{
A& a = GetNextA();

a.DoSomeThing();
}

Since "a" is not declared static, it gets initalized everytime code passes through
the block.
while (1)
{
{
A& a = GetNextA();

a.DoSomeThing();
}
}
The extra { } have no additional effect here.
On a related note, is it possible to prevent a reference to a class
instance? Similarly, is it possible to prevent the address of an instance
from being taken?
You can't do anything to prevent a value from being bound to a reference.
You can make taking the address of it difficult, by overloading the unary
& operator for the class, but I'm not certain that would be a fool proof
way of disabling it entirely.

What I'm looking for is a way to implement a 'Reference<T>' class. In other
words, some kind of class like a smart-pointer except that the 'Reference'
is the only way to access the object to which it refers. I want to prevent
'address-of' and references and use the 'Reference' as a means to manage
object life-time.


I'm unclear of what you're really trying to accomplish, however provided you don't
specifically provide a way to do with it, a Reference<T> wouldn't be bindable to T&.
However such a class would have other problems. Specifically, you can't overload
operator (period). .

Jul 22 '05 #2
Tim Clacy wrote:
Am I correct in think that you can't re-assign a reference to a different
object? If so, what should happen here:
Yes.

[snip] {
A& a = GetNextA();

a.DoSomeThing();
}
The object "a" only exists within this scope. Once the scope is left it
should be destroyed. When the loop re-enters the scope a new object,
also called "a", will be created.

I suppose compiler optimisations might change this behaviour in some
unnoticeable way.

Note that I'm not certain about any of this. You could always try it and
see what your compiler does.
Does reference 'a' only get assigned first time around the loop and,
thereafter, object 'a' gets assigned to the next 'A'... or is 'a' connected
to a different 'A' every time around the loop? What about this:

while (1)
{
{
A& a = GetNextA();

a.DoSomeThing();
}
}
Call me crazy, but isn't that identical to the last bit of code? You're
just adding an extra (redundant) scope.
Surely, 'a' would now be different every time around the loop (because the
scope of 'a' ends before looping?
Yes, I'm pretty sure they are the same.
On a related note, is it possible to prevent a reference to a class
instance? Similarly, is it possible to prevent the address of an instance
from being taken?

What I'm looking for is a way to implement a 'Reference<T>' class. In other
words, some kind of class like a smart-pointer except that the 'Reference'
is the only way to access the object to which it refers. I want to prevent
'address-of' and references and use the 'Reference' as a means to manage
object life-time.


I do this by writing public static "Create" methods in each class that
return a smart pointer to the new object. All constructors are
private/protected so there is no way of creating the object outside of
the static methods. Consequently there is no direct access to the object
itself (only through the smart pointer), so a reference or pointer to it
cannot be obtained (unless the smart pointer allows it).

Like this:

class SafeObject
{
public:
static MySmartPtr< SafeObject > Create();

private:
SafeObject() {}

// Probably don't need private copy-ctors or copy-assignment
// operators, because you can't access the object directly
// to use them with anyway.
};

Where "MySmartPtr" is your "Reference" class template. You will be able
to take a reference or pointer of MySmartPtr, but not of SafeObject
directly (to the best of my knowledge).

Hope that helps.

-- Pete
Jul 22 '05 #3
Pete Vidler wrote:
Tim Clacy wrote:
Am I correct in think that you can't re-assign a reference to a
different object? If so, what should happen here:
Yes.

[snip]
{
A& a = GetNextA();

a.DoSomeThing();
}


The object "a" only exists within this scope. Once the scope is left
it should be destroyed. When the loop re-enters the scope a new
object,
also called "a", will be created.


Pete,

Hi. So when you loop, this is like leaving a scope then re-entering?
I suppose compiler optimisations might change this behaviour in some
unnoticeable way.

Note that I'm not certain about any of this. You could always try it
and
see what your compiler does.
Does reference 'a' only get assigned first time around the loop and,
thereafter, object 'a' gets assigned to the next 'A'... or is 'a'
connected to a different 'A' every time around the loop? What about
this:

while (1)
{
{
A& a = GetNextA();

a.DoSomeThing();
}
}
Call me crazy, but isn't that identical to the last bit of code?
You're
just adding an extra (redundant) scope.
Surely, 'a' would now be different every time around the loop
(because the scope of 'a' ends before looping?


Yes, I'm pretty sure they are the same.


Yep, it sounds like they are the same. I wasn't (still not) entirely clear
about life-time of variables/references/objects inside a loop scope. If
variables/references/objects are destroyed and re-constructed every loop
cycle, then my second case is the same as the first.
On a related note, is it possible to prevent a reference to a class
instance? Similarly, is it possible to prevent the address of an
instance from being taken?

What I'm looking for is a way to implement a 'Reference<T>' class.
In other words, some kind of class like a smart-pointer except that
the 'Reference' is the only way to access the object to which it
refers. I want to prevent 'address-of' and references and use the
'Reference' as a means to manage object life-time.


I do this by writing public static "Create" methods in each class that
return a smart pointer to the new object. All constructors are
private/protected so there is no way of creating the object outside of
the static methods. Consequently there is no direct access to the
object itself (only through the smart pointer), so a reference or
pointer to it cannot be obtained (unless the smart pointer allows it).

Like this:

class SafeObject
{
public:
static MySmartPtr< SafeObject > Create();

private:
SafeObject() {}

// Probably don't need private copy-ctors or copy-assignment
// operators, because you can't access the object directly
// to use them with anyway.
};

Where "MySmartPtr" is your "Reference" class template. You will be
able
to take a reference or pointer of MySmartPtr, but not of SafeObject
directly (to the best of my knowledge).

Hope that helps.


Hmm, that's about where I am right now... but all we've done is replaced the
problem of controlling the object life-time with a problem of controlling
the smart-pointer life-time.

-- Pete

Jul 22 '05 #4
Ron Natalie wrote:
"Tim Clacy" <no*******@nospamphaseone.nospamdk> wrote in message
news:40*********************@dread11.news.tele.dk. ..
while (1)
{
A& a = GetNextA();

a.DoSomeThing();
}

Since "a" is not declared static, it gets initalized everytime code
passes through
the block.
while (1)
{
{
A& a = GetNextA();

a.DoSomeThing();
}
}


The extra { } have no additional effect here.
On a related note, is it possible to prevent a reference to a class
instance? Similarly, is it possible to prevent the address of an
instance
from being taken?


You can't do anything to prevent a value from being bound to a
reference.


Ron,

Hi. Doesn't this mean that there is no automatic way to manage object
life-time (because anyone can just connect a C++ reference to any object)?
You can make taking the address of it difficult, by overloading the
unary & operator for the class, but I'm not certain that would be a
fool proof
way of disabling it entirely.

What I'm looking for is a way to implement a 'Reference<T>' class.
In other
words, some kind of class like a smart-pointer except that the
'Reference'
is the only way to access the object to which it refers. I want to
prevent 'address-of' and references and use the 'Reference' as a
means to manage
object life-time.


I'm unclear of what you're really trying to accomplish, however
provided you don't
specifically provide a way to do with it, a Reference<T> wouldn't be
bindable to T&.
However such a class would have other problems. Specifically, you
can't overload
operator (period). .


....hmm, so the long and the short of it is that if you don't mind using '->'
to access objects you can almost acheive automatic object life-time, but if
you want to use '.' you have to use C++ references, which are an
object-life-time management nightmare?

Regards
Tim
Jul 22 '05 #5
Tim Clacy wrote:
[snip]
Hi. So when you loop, this is like leaving a scope then re-entering?
Effectively, yes.

[snip]
Yes, I'm pretty sure they are the same.


Yep, it sounds like they are the same. I wasn't (still not) entirely clear
about life-time of variables/references/objects inside a loop scope. If
variables/references/objects are destroyed and re-constructed every loop
cycle, then my second case is the same as the first.


Of course, I'm not exactly certain about this. Consider the fact that,
in a "for( int i =... )" loop, the i variable is considered to be inside
the loop's scope. It doesn't get deleted and reconstructed each time,
though.

I'm just confusing myself now. In reality all this is rarely an issue.
If you need a variable in every loop cycle, declare it outside the loop.

[snip] Hmm, that's about where I am right now... but all we've done is replaced the
problem of controlling the object life-time with a problem of controlling
the smart-pointer life-time.

[snip]

Smart pointers are typically reference counted. If all you really want
is a smart pointer, check out boost::shared_ptr from www.boost.org. I
can highly recommend it (and the rest of that library).

As an aside about shifting the problem onto a separate class, this is a
common technique in C++. The answer to many problems seems to be adding
an extra layer of indirection (so I've heard).

-- Pete
Jul 22 '05 #6
Pete Vidler wrote:
Tim Clacy wrote:

[snip]
Hi. So when you loop, this is like leaving a scope then re-entering?
Effectively, yes.

[snip]
Yes, I'm pretty sure they are the same.


Yep, it sounds like they are the same. I wasn't (still not) entirely
clear
about life-time of variables/references/objects inside a loop scope. If
variables/references/objects are destroyed and re-constructed every loop
cycle, then my second case is the same as the first.


Of course, I'm not exactly certain about this. Consider the fact that,
in a "for( int i =... )" loop, the i variable is considered to be inside
the loop's scope. It doesn't get deleted and reconstructed each time,
though.


There are two nested scopes associated with for loops: an outer scope
for any declaration-definition in the 'for' initializer, and an inner
scope for the loop body. The inner scope may or may not be marked
explicitly with braces but it's always there. The outer scope is entered
once at the beginning of the construct and left once after all
iterations are complete. The inner scope is entered and left on every
iteration.

For while loops, the scope of a declaration in the 'while' condition
contains the scope of the loop body and is entered and left once for
every iteration. It's less important here to make the 'two scopes'
distinction. The same is true of declarations in 'if' conditions.
('switch' too?)

You can depend on this absolutely. Optimization won't change the meaning
of your code. The one small snag is that there are compilers that use
obsolete rules for the scope of declarations in for, while and if
statements. Hopefully it's no longer necessary to think about that.
[...]


Regards,
Buster.
Jul 22 '05 #7
Pete Vidler wrote:
Tim Clacy wrote:
[snip]
Hi. So when you loop, this is like leaving a scope then re-entering?
Effectively, yes.

[snip]
Yes, I'm pretty sure they are the same.


Yep, it sounds like they are the same. I wasn't (still not) entirely
clear about life-time of variables/references/objects inside a loop
scope. If variables/references/objects are destroyed and
re-constructed every loop cycle, then my second case is the same as
the first.


Of course, I'm not exactly certain about this. Consider the fact that,
in a "for( int i =... )" loop, the i variable is considered to be
inside
the loop's scope. It doesn't get deleted and reconstructed each time,
though.

I'm just confusing myself now. In reality all this is rarely an issue.
If you need a variable in every loop cycle, declare it outside the
loop.

[snip]
Hmm, that's about where I am right now... but all we've done is
replaced the problem of controlling the object life-time with a
problem of controlling the smart-pointer life-time.

[snip]

Smart pointers are typically reference counted. If all you really want
is a smart pointer, check out boost::shared_ptr from www.boost.org. I
can highly recommend it (and the rest of that library).


I've have perused Boost (some of the 15MB) and there's some awfully clever
stuff in there. However, what's to stop someone taking a C++ reference to a
smart-pointer (i.e. defeating the purpose)?
As an aside about shifting the problem onto a separate class, this is
a common technique in C++. The answer to many problems seems to be
adding
an extra layer of indirection (so I've heard).

-- Pete

Jul 22 '05 #8
Buster wrote:
Pete Vidler wrote:
Tim Clacy wrote:
>
[snip]
Hi. So when you loop, this is like leaving a scope then re-entering?


Effectively, yes.
>
[snip]
Yes, I'm pretty sure they are the same.

Yep, it sounds like they are the same. I wasn't (still not) entirely
clear
about life-time of variables/references/objects inside a loop
scope. If variables/references/objects are destroyed and
re-constructed every loop cycle, then my second case is the same as
the first.


Of course, I'm not exactly certain about this. Consider the fact
that, in a "for( int i =... )" loop, the i variable is considered to
be inside the loop's scope. It doesn't get deleted and reconstructed
each time, though.


There are two nested scopes associated with for loops: an outer scope
for any declaration-definition in the 'for' initializer, and an inner
scope for the loop body. The inner scope may or may not be marked
explicitly with braces but it's always there. The outer scope is
entered once at the beginning of the construct and left once after all
iterations are complete. The inner scope is entered and left on every
iteration.

For while loops, the scope of a declaration in the 'while' condition
contains the scope of the loop body and is entered and left once for
every iteration. It's less important here to make the 'two scopes'
distinction. The same is true of declarations in 'if' conditions.
('switch' too?)

You can depend on this absolutely. Optimization won't change the
meaning of your code. The one small snag is that there are compilers
that use obsolete rules for the scope of declarations in for, while
and if statements. Hopefully it's no longer necessary to think about
that.
> [...]


Regards,
Buster.


Cheers.
Jul 22 '05 #9
* "Tim Clacy" <no*******@nospamphaseone.nospamdk> schriebt:
Hi. Doesn't this mean that there is no automatic way to manage object
life-time (because anyone can just connect a C++ reference to any object)?


In theory yes. In practice no. Both because code that does that breaks
the contract, and because you _can_ (although no one does) make it
utterly impractical to obtain a direct reference.

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #10
Tim Clacy wrote:
[snip]
I've have perused Boost (some of the 15MB) and there's some awfully clever
stuff in there. However, what's to stop someone taking a C++ reference to a
smart-pointer (i.e. defeating the purpose)?

[snip]

Nothing prevents it. It just isn't a problem.

Unless you have a specific situation where it could be a problem?

-- Pete
Jul 22 '05 #11

"Tim Clacy" <no*******@nospamphaseone.nospamdk> wrote in message
news:40*********************@dread11.news.tele.dk. ..
Pete Vidler wrote:
Tim Clacy wrote:
[snip]
Hi. So when you loop, this is like leaving a scope then re-entering?
Effectively, yes.

[snip] Smart pointers are typically reference counted. If all you really want
is a smart pointer, check out boost::shared_ptr from www.boost.org. I
can highly recommend it (and the rest of that library).


I've have perused Boost (some of the 15MB) and there's some awfully clever
stuff in there. However, what's to stop someone taking a C++ reference to

a smart-pointer (i.e. defeating the purpose)?


How? Can you show a case where it's an issue? A typical usage would be:

struct A
{
...

bool GotMilk()const{ return true; }
};

void somefunction( A& aRef )
{
bool lGood = aRef.GotMilk():
}

void SomeOtherFunction()
{
boost::shared_ptr<A> lAPtr( new A );

...

somefunction( *lAPtr ); // reference valid for the
// duration of somefunction
// indeed for this entire scope
...

} //

Jeff F
Jul 22 '05 #12
Alf P. Steinbach wrote:
* "Tim Clacy" <no*******@nospamphaseone.nospamdk> schriebt:
Hi. Doesn't this mean that there is no automatic way to manage object
life-time (because anyone can just connect a C++ reference to any
object)?


In theory yes. In practice no. Both because code that does that
breaks the contract, and because you _can_ (although no one does)
make it
utterly impractical to obtain a direct reference.


Alf,

Hi. How can one make it impractical to obtain a direct reference to an
object; others are saying that you can't do that?
Tim
Jul 22 '05 #13
Pete Vidler wrote:
Tim Clacy wrote:
[snip]
I've have perused Boost (some of the 15MB) and there's some awfully
clever stuff in there. However, what's to stop someone taking a C++
reference to a smart-pointer (i.e. defeating the purpose)? [snip]

Nothing prevents it. It just isn't a problem.


....hmm, don't you think robust object life-time management is just about the
most important thing to get right to help ensure a robust, quality product?
My experience is that if something is fragile, sooner or later, it will
break... but perhaps I've just been unlucky?
Unless you have a specific situation where it could be a problem?

-- Pete

Jul 22 '05 #14
Jeff Flinn wrote:
"Tim Clacy" <no*******@nospamphaseone.nospamdk> wrote in message
news:40*********************@dread11.news.tele.dk. ..
Pete Vidler wrote:
Tim Clacy wrote:
[snip]
Hi. So when you loop, this is like leaving a scope then
re-entering?

Effectively, yes.

[snip] Smart pointers are typically reference counted. If all you really
want is a smart pointer, check out boost::shared_ptr from
www.boost.org. I can highly recommend it (and the rest of that
library).
I've have perused Boost (some of the 15MB) and there's some awfully
clever stuff in there. However, what's to stop someone taking a C++
reference to a smart-pointer (i.e. defeating the purpose)?


How? Can you show a case where it's an issue? A typical usage would
be:

struct A
{
...

bool GotMilk()const{ return true; }
};

void somefunction( A& aRef )
{
bool lGood = aRef.GotMilk():
}

void SomeOtherFunction()
{
boost::shared_ptr<A> lAPtr( new A );

...

somefunction( *lAPtr ); // reference valid for the
// duration of somefunction
// indeed for this entire scope


What if somefunction assigns a static or class member to that reference...
or copies it to another thread?

} //

Jeff F

Jul 22 '05 #15
Tim Clacy wrote:
[snip]
Nothing prevents it. It just isn't a problem.


...hmm, don't you think robust object life-time management is just about the
most important thing to get right to help ensure a robust, quality product?
My experience is that if something is fragile, sooner or later, it will
break... but perhaps I've just been unlucky?

[snip]

Yes, but using a smart pointer is just about as robust as it gets. You
still haven't explained how it isn't robust -- there's nothing wrong
with taking a reference to the smart pointer that I can see. So long as
you don't mess with raw pointers your app will be perfectly robust.

The only problem would be if you could assing a temporary object to a
reference, but I'm pretty sure the standard forbids it. You can assign
temporaries to const references, but then the lifetime of the temporary
is guaranteed to be at least as long as the lifetime of the const
reference (I believe).

-- Pete
Jul 22 '05 #16
Tim Clacy wrote:
[snip]
What if somefunction assigns a static or class member to that reference...
or copies it to another thread?

[snip]

In the case of a programmer assigning static members to references, the
fool deserves everything he gets. You can protect programmers from
themselves only so far.

In the given example you cannot reassign a reference. It just isn't
legal C++. You can alter the object that the reference is of, in ways
determined by the interface of its class (providing it's a non-const
reference), but that's about it.

-- Pete
Jul 22 '05 #17
"Pete Vidler" <pv*****@mailblocks.com> wrote in message
news:ba***************@newsfe1-gui.server.ntli.net...
Tim Clacy wrote:
[snip]
Nothing prevents it. It just isn't a problem.
...hmm, don't you think robust object life-time management is just about the most important thing to get right to help ensure a robust, quality product? My experience is that if something is fragile, sooner or later, it will
break... but perhaps I've just been unlucky?

[snip]

Yes, but using a smart pointer is just about as robust as it gets. You
still haven't explained how it isn't robust -- there's nothing wrong
with taking a reference to the smart pointer that I can see. So long as
you don't mess with raw pointers your app will be perfectly robust.


I'm almost convinced... provided that it is possible to ensure that only the
smart pointer can do the creation of the object and that it's not possible
to 'new' smart pointers (so the life-time of the smart-pointer is under
control) and it's not possible to take the address of smart pointers. That
should all be acheivable shouldn't it?

I think I'll spend the weekend studying Boost's smart pointer.

Cheers
The only problem would be if you could assing a temporary object to a
reference, but I'm pretty sure the standard forbids it. You can assign
temporaries to const references, but then the lifetime of the temporary
is guaranteed to be at least as long as the lifetime of the const
reference (I believe).

-- Pete


Jul 22 '05 #18
* "Tim Clacy" <no*******@nospamphaseone.nospamdk> schriebt:

How can one make it impractical to obtain a direct reference to an
object


This was discussed in
<url:
http://www.google.com/groups?threadm=c0aur7%2414gog5%241%40ID-14036.news.uni-berlin.de>

Summary of proposed solutions in the context of preventing deletion via
a raw pointer obtained from a smart-pointer class:

Andrei Alexandrescu, Thomas Mang, Steve Dewhurst:
Let operator-> return a proxy (and Andrei, of course, further proposed
using a recursive template to generate a proxy to proxy to proxy..., say
to 100 levels, to really make it hard for client code to get the address).

Paavo Helde:
If you own the implementation of the class A that the smart pointer
encapsulates, let its destructor be protected and let the smart
pointer's operator-> return a pointer to a derived class instance.

Niklas Borson:
Let the smart pointer be a wrapper class with one wrapper function
for each function of the wrapped class, instead of using operator->.

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #19
Tim Clacy wrote:
[snip]
I'm almost convinced... provided that it is possible to ensure that only the
smart pointer can do the creation of the object and that it's not possible
to 'new' smart pointers (so the life-time of the smart-pointer is under
control) and it's not possible to take the address of smart pointers. That
should all be acheivable shouldn't it?

[snip]

The basics are straight from the FAQ:

class SafeClass
{
public:
typedef boost::shared_ptr< SafeClass > Ptr;

// Might need a static_cast here, I don't remember exactly.
Ptr Create() { return new SafeClass; }

private:
SafeClass() { ... }
};

// This should be the only way to create a SafeClass object:
SafeClass::Ptr safeClass1 = SafeClass::Create();

This meets my top two criteria -- safe and readable.

In the thread "Base class method that returns a pointer to a derived
class?" on this newsgroup I've detailed a technique for extending this
to a hierarchy (from Maxim Yegorushkin on comp.lang.c++.moderated).

-- Pete
Jul 22 '05 #20
Pete Vidler wrote:
[snip]
class SafeClass
{
public:
typedef boost::shared_ptr< SafeClass > Ptr;

// Might need a static_cast here, I don't remember exactly.
Ptr Create() { return new SafeClass; }
That Create method was meant to be static, obviously.
private:
SafeClass() { ... }
};

// This should be the only way to create a SafeClass object:
SafeClass::Ptr safeClass1 = SafeClass::Create();


-- Pete
Jul 22 '05 #21
Pete Vidler wrote:
[snip]
class SafeClass
{
public:
typedef boost::shared_ptr< SafeClass > Ptr;

// Might need a static_cast here, I don't remember exactly.
Ptr Create() { return new SafeClass; }
That Create method was meant to be static, obviously.
private:
SafeClass() { ... }
};

// This should be the only way to create a SafeClass object:
SafeClass::Ptr safeClass1 = SafeClass::Create();


-- Pete
Jul 22 '05 #22
Tim
"Pete Vidler" <pv*****@mailblocks.com> wrote in message
news:gM*************@newsfe5-gui.server.ntli.net...
Pete Vidler wrote:
[snip]
class SafeClass
{
public:
typedef boost::shared_ptr< SafeClass > Ptr;

// Might need a static_cast here, I don't remember exactly.
Ptr Create() { return new SafeClass; }


That Create method was meant to be static, obviously.
private:
SafeClass() { ... }
};

// This should be the only way to create a SafeClass object:
SafeClass::Ptr safeClass1 = SafeClass::Create();


-- Pete


Don't we have an even worse issue here; what if someone makes a reference to
the returned temporary instead of copying it:

SafeClass::Ptr& safeClass1 = SafeClass::Create();

Now the instance of SafeClass is a bona-fide memory leak.

Jul 22 '05 #23
Tim
"Pete Vidler" <pv*****@mailblocks.com> wrote in message
news:gM*************@newsfe5-gui.server.ntli.net...
Pete Vidler wrote:
[snip]
class SafeClass
{
public:
typedef boost::shared_ptr< SafeClass > Ptr;

// Might need a static_cast here, I don't remember exactly.
Ptr Create() { return new SafeClass; }


That Create method was meant to be static, obviously.
private:
SafeClass() { ... }
};

// This should be the only way to create a SafeClass object:
SafeClass::Ptr safeClass1 = SafeClass::Create();


-- Pete


Don't we have an even worse issue here; what if someone makes a reference to
the returned temporary instead of copying it:

SafeClass::Ptr& safeClass1 = SafeClass::Create();

Now the instance of SafeClass is a bona-fide memory leak.

Jul 22 '05 #24
Tim

"Pete Vidler" <pv*****@mailblocks.com> wrote in message
news:bfgbc.204$%m5.81@newsfe1-win...
Tim Clacy wrote:
[snip]
What if somefunction assigns a static or class member to that reference... or copies it to another thread?

[snip]

In the case of a programmer assigning static members to references, the
fool deserves everything he gets. You can protect programmers from
themselves only so far.

In the given example you cannot reassign a reference. It just isn't
legal C++. You can alter the object that the reference is of, in ways
determined by the interface of its class (providing it's a non-const
reference), but that's about it.

-- Pete


But the big problem, surely, is that when the reference goes out of scope,
the destructor of the object to which it refers is not called and we have a
lingering object. It seems much easier to make reference to instances than
to ensure that those instances are cleaned-up when its referees expire.
Jul 22 '05 #25
Tim

"Pete Vidler" <pv*****@mailblocks.com> wrote in message
news:bfgbc.204$%m5.81@newsfe1-win...
Tim Clacy wrote:
[snip]
What if somefunction assigns a static or class member to that reference... or copies it to another thread?

[snip]

In the case of a programmer assigning static members to references, the
fool deserves everything he gets. You can protect programmers from
themselves only so far.

In the given example you cannot reassign a reference. It just isn't
legal C++. You can alter the object that the reference is of, in ways
determined by the interface of its class (providing it's a non-const
reference), but that's about it.

-- Pete


But the big problem, surely, is that when the reference goes out of scope,
the destructor of the object to which it refers is not called and we have a
lingering object. It seems much easier to make reference to instances than
to ensure that those instances are cleaned-up when its referees expire.
Jul 22 '05 #26
Tim wrote:
[snip]
Don't we have an even worse issue here; what if someone makes a reference to
the returned temporary instead of copying it:

SafeClass::Ptr& safeClass1 = SafeClass::Create();

Now the instance of SafeClass is a bona-fide memory leak.

[snip]

No it isn't. The standard forbids assigning a temporary to a non-const
reference. It won't even compile (with a half decent compiler).

If you used a const-reference, the object is guaranteed to survive at
least as long as the const-reference.

Besides, that isn't a memory leak even if it was allowed. The smart
pointer will always free the memory, it's just that the reference would
then be invalid. But it can't happen, so it doesn't matter.

-- Pete
Jul 22 '05 #27
Tim wrote:
[snip]
Don't we have an even worse issue here; what if someone makes a reference to
the returned temporary instead of copying it:

SafeClass::Ptr& safeClass1 = SafeClass::Create();

Now the instance of SafeClass is a bona-fide memory leak.

[snip]

No it isn't. The standard forbids assigning a temporary to a non-const
reference. It won't even compile (with a half decent compiler).

If you used a const-reference, the object is guaranteed to survive at
least as long as the const-reference.

Besides, that isn't a memory leak even if it was allowed. The smart
pointer will always free the memory, it's just that the reference would
then be invalid. But it can't happen, so it doesn't matter.

-- Pete
Jul 22 '05 #28
"Tim Clacy" wrote:
Pete Vidler wrote:
Tim Clacy wrote:
I've have perused Boost (some of the 15MB) and there's some awfully
clever stuff in there. However, what's to stop someone taking a C++
reference to a smart-pointer (i.e. defeating the purpose)?
Nothing prevents it. It just isn't a problem.


...hmm, don't you think robust object life-time management is just about the
most important thing to get right to help ensure a robust, quality product?


No! I'm firmly on the Murphy side (and you seem to be on the
Machiavelli side): I think the idea is to make sure the users of your
library don't screw up accidentally, but not to try and prevent them
screwing up on purpose. No matter what measures you take, there
will always be a way to get around them if someone is hell-bent on
doing so.
My experience is that if something is fragile, sooner or later, it will
break... but perhaps I've just been unlucky?


What does 'pointer' have to do with 'fragile' ?
If someone creates and deletes your objects, good on them. You
don't have to try and prevent people from forgetting to free a
pointer, for example.
IMHO, adding more complexity to your class to guard against nasty
people, is just making it more fragile.
Jul 22 '05 #29
"Tim Clacy" wrote:
Pete Vidler wrote:
Tim Clacy wrote:
I've have perused Boost (some of the 15MB) and there's some awfully
clever stuff in there. However, what's to stop someone taking a C++
reference to a smart-pointer (i.e. defeating the purpose)?
Nothing prevents it. It just isn't a problem.


...hmm, don't you think robust object life-time management is just about the
most important thing to get right to help ensure a robust, quality product?


No! I'm firmly on the Murphy side (and you seem to be on the
Machiavelli side): I think the idea is to make sure the users of your
library don't screw up accidentally, but not to try and prevent them
screwing up on purpose. No matter what measures you take, there
will always be a way to get around them if someone is hell-bent on
doing so.
My experience is that if something is fragile, sooner or later, it will
break... but perhaps I've just been unlucky?


What does 'pointer' have to do with 'fragile' ?
If someone creates and deletes your objects, good on them. You
don't have to try and prevent people from forgetting to free a
pointer, for example.
IMHO, adding more complexity to your class to guard against nasty
people, is just making it more fragile.
Jul 22 '05 #30

This discussion thread is closed

Replies have been disabled for this discussion.

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.