Poll: Do you use smart pointers?

R

Roland Pibinger

Well, someone else showed how inefficient use of certain constructs
results in inefficient code but when a ref-counted smart pointer is
actually needed is it really less efficient than the raw pointer
alternative?

Yes, of course. Actually, inefficiency is Stroustrups major argument
against ref-counted s.p. (http://www.research.att.com/~bs/DnE2005.pdf
look for "Smart pointer"). IMO, 'transfer' semantics is the stronger
argument against s.p.
Since ref counted smart pointers are meant to aliviate
the difficulties associated with ownership semantics

S.p. create more problems WRT ownership that they solve.
what is your raw
pointer alternative that is so much more efficient?

RAII. I mean pure RAII so that "allocation and deallocation disappear
from the surface level of your code"
(http://www.artima.com/intv/modern3.html). Encapsulation without
transfer of ownership.

Best wishes,
Roland Pibinger
 
T

Thomas J. Gritzan

boost::intrusive_ptr is another example.

Noah said:
It's also not the only smart pointer available...not even the only one
available in tr1. The whole purpose of weak_ptr is to use shared_ptr
without the costs when unnecissary, such as passing shared_ptrs as
arguments or returns (except in cases like above of course).

Huh? What costs does shared_ptr have that weak_ptr doesn't have?

weak_ptr holds a pointer that doesn't go into the reference count, which is
usefull to break circular references.
 
R

Roland Pibinger

True of std::auto_ptr

and shared_ptr and ...
if you don't know what you're doing, and of raw
pointers as well (again, if you don't know what you're doing). Not
true of reference-counted pointers.

Real pointers don't transfer ownership because the never own any
pointed-to object.
i.e., people who use them not understanding what they're doing. But
the same is true of raw pointers - if you don't know what you're doing,
a lot of error-prone usage. Smart pointers work fine when used as
directed.

Of course, you always should understanding what you're doing. But the
point is that there are better and worse interfaces.
The C++ Standard library doesn't 'new' anything what has to be deleted
by the user and, vice versa, doesn't delete anything that has been
'newed' by the user (similar in C with malloc/free). The only
exception is auto_ptr (and shared_ptr in the future) which violates
that principle.
How do you write exception-safe code without them? Do you simply not
use exceptions and assume your use of library functions won't throw?
Do you have elaborate try-catch blocks every time you allocate from the
free-store?

No try/catch cascades, just pure RAII as described by Stroustrup:
http://www.artima.com/intv/modern3.html. The pattern was called
"Object As Sole Owner" by Cargill in his seminal article which is now
available online: http://www.ddj.com/184409895 (BTW, objects typically
are not created in the constructor but in any member function).

Best regards,
Roland Pibinger
 
M

mlimber

Roland said:
Yes, of course. Actually, inefficiency is Stroustrups major argument
against ref-counted s.p. (http://www.research.att.com/~bs/DnE2005.pdf
look for "Smart pointer").

The key part is: 'Smart pointers are popular, but should be approached
with care. They are not the panacea that they are sometimes presented
to be. In particular, they are far more expensive to use than ordinary
pointers, destructors for objects "owned" by a set of shared_ptrs
will run at unpredictable times, and if a lot of objects are deleted at
once because the last shared_ptr to them is deleted you can incur
"garbage collection delays" exactly as if you were running a
general collector. The costs primarily relate to free store allocation
of use count objects and especially to locking during access to the use
counts in threaded systems. Do not simply replace all your ordinary
pointers with smart_ptrs if you are concerned with performance or
predictability. These concerns kept smart_ptrs "ancestor",
counted_ptr, out of the 1998 standard.'

It is not likely, however, that these concerns will keep them out of
C++0x, not least because our collective experienced with smart pointers
has increased since 1998. Not to disregard the venerable Creator's
words, but other gurus have made the opposite case that "Correctness is
worth the cost [of smart pointers]" (C++ Coding Standards, item 60),
and they suggest "If you use [Boost] and [TR1] for nothing else, use
them for shared_ptr."
IMO, 'transfer' semantics is the stronger argument against s.p.

Please elaborate. (We all know about std::auto_ptr. What about
std::tr1::shared_ptr or boost::scoped_ptr, which doesn't allow
transferring at all?)
S.p. create more problems WRT ownership that they solve.

Bald assertions don't prove your case.
RAII. I mean pure RAII so that "allocation and deallocation disappear
from the surface level of your code"
(http://www.artima.com/intv/modern3.html). Encapsulation without
transfer of ownership.

The explicit purpose of std::auto_ptr is to support RAII (TC++PL,
14.4.2).

Cheers! --M
 
T

tryptik

Someone made the statement in a newsgroup that most C++ programmers use
smart pointers. His actual phrase was "most of us" but I really don't think
that most C++ programmers use smart pointers, but I just don't know.

I am a C++ noob, but I am a total fan of boost pointers and I use them
wnever possible. The only time I don't is when I want non-ownership
access to an object that is on the stack.

They are totally worth the time and effort to learn about them and I
think they should become part of the C++ standard library.
 
N

Noah Roberts

Thomas said:
What costs does shared_ptr have that weak_ptr doesn't have?

weak_ptr doesn't do any counting. It provides access to the pointer
and to the reference when needed but doesn't do any upkeep so is pretty
close to a raw pointer. The only time you pay reference costs with a
weak ptr is when you try to create a shared_ptr out of it. It does
have extra space requirements to access the reference count (maybe, not
really sure) so still isn't appropriate for the use in question but it
still lessens the cost of using shared_ptr objects by providing a non
counting interface when such a count isn't useful.
 
R

Roland Pibinger

It is not likely, however, that these concerns will keep them out of
C++0x,

bad for C++38 ...
not least because our collective experienced with smart pointers
has increased since 1998. Not to disregard the venerable Creator's
words, but other gurus have made the opposite case that "Correctness is
worth the cost [of smart pointers]" (C++ Coding Standards, item 60),
and they suggest "If you use [Boost] and [TR1] for nothing else, use
them for shared_ptr."

Which "Correctness"? The 'usual' smart pointers use questionable
"transfer of ownership" semantics and don't check for NULL before they
dereference a pointer. The following compiles without a warning on
popular compilers:

int i = 0;
auto_ptr<int> ap (&i);

BTW, even gurus may change their mind
(http://www.gotw.ca/publications/index.htm):
"Most people have heard of the standard auto_ptr smart pointer
facility, but not everyone uses it daily. That's a shame, because it
turns out that auto_ptr neatly solves common C++ design and coding
problems, and using it well can lead to more robust code." Herb
Sutter, 1999

"Avoid using auto_ptr, instead use shared_ptr which is widely
available and being added to the standard library." Herb Sutter,
2004.

Best wishes,
Roland Pibinger
 
A

Alf P. Steinbach

* Noah Roberts:
weak_ptr doesn't do any counting. It provides access to the pointer
and to the reference when needed but doesn't do any upkeep so is pretty
close to a raw pointer.

Are you sure about that? I haven't checked any implementation, but a
weak pointer must be able to detect whether the managed object still
exists or not, in order to not conjure up a non-null shared_ptr for an
already destroyed object. Thus, I think it likely that for a shared_ptr
managed object O there exists a hidden reference holder object, call it
Refs, that contains (1) a raw pointer to O, (2) a count nHardRefs of
shared_ptr instances for O, and (3) a count nWeakRefs of weak_ptr
instances for O, such that O is destroyed when nHardRefs goes to zero,
and Refs is destroyed at that point iff nWeakRefs is 0, or later on when
nWeakRefs goes to zero -- which implies weak_ptr reference counting.
 
T

Thomas J. Gritzan

Noah said:
weak_ptr doesn't do any counting. It provides access to the pointer
and to the reference when needed but doesn't do any upkeep so is pretty
close to a raw pointer.

Wrong.

A shared_ptr object holds to pointers: One to the counted object, one to
the management structure. The last shared_ptr object drops the reference
count to zero and deletes the counted object.

But the management structure is also a shared object and can't be deleted
until the last weak_ptr is gone. So weak_ptr does count.

I just checked in my boost implementation: weak_ptr holds a weak_count
object, which does this in its destructor:

~weak_count() // nothrow
{
if(pi_ != 0) pi_->weak_release();
// [...]
}

And some add_ref calls in the constructors and assignment operators.
 
N

Noah Roberts

Alf said:
* Noah Roberts:

Are you sure about that? I haven't checked any implementation, but a
weak pointer must be able to detect whether the managed object still
exists or not, in order to not conjure up a non-null shared_ptr for an
already destroyed object.

Nope, I hadn't thought of that. This is why I don't spend a lot of
time trying to make my own when not forced to by management. We
haven't even reached the point where you are - we still use raw
pointers except where I've used a broken smart pointer I made for a
particular purpose. Everyone else is miles from being convinced to use
them. So we play with leaks and dangling pointers instead.
 
J

Jens Theisen

Real pointers don't transfer ownership because the never own any
pointed-to object.

Whether or not ownership is transferred is a conceptional issue. If
the code calling the pointer-producing function is supposed to free
the pointer than ownership is transferred.
No try/catch cascades, just pure RAII as described by Stroustrup:
http://www.artima.com/intv/modern3.html.

So how does that differ from shared_ptr? shared_ptr doesn't transfer
ownership, shared_ptr keeps ownership. That's exactly what Stroustrup
was promoting.

The only minor exception is during initialisation:

shared_ptr< some_t > ptr(new some_t(...));

But that's highly idiomatic.

Is this initialisation what the fuss is about?

If so, write a small wrapper

template< typename T > // this following for any number of params
shared_ptr< T > init_shared_ptr(T1 const& t1, T2 const& t2)
{
return shared_ptr< T >(new T(t1, t2));
}

and take shared_ptr and init_shared_ptr _together_ as a library that
confines ownership.

Jens
 
D

David Harmon

On Fri, 22 Sep 2006 20:22:30 GMT in comp.lang.c++, (e-mail address removed)
(Roland Pibinger) wrote,
Which "Correctness"? The 'usual' smart pointers use questionable
"transfer of ownership" semantics and don't check for NULL before they
dereference a pointer. The following compiles without a warning on
popular compilers:

int i = 0;
auto_ptr<int> ap (&i);

The above is a user problem, not a auto_ptr problem. The same as if
you just wrote 'delete &i;'

In my opinion, auto_ptr should no longer be regarded as "the usual"
smart pointer, at least for new code. Boost::shared_ptr is my usual
smart pointer, with safer and more flexible behavior at the cost of
some comparatively very cheap memory and CPU cycles. tr1:: if you
have it.

auto_ptr is still OK in cases where it applies. I fixed some code
based on a Microsoft sample by adding some auto_ptr<>s. The API
returns pointers to 'new'ed objects (for no good reason) that the
user is responsible to delete. The original example code leaked
left and right on all the error return paths.
BTW, even gurus may change their mind
(http://www.gotw.ca/publications/index.htm):
"Most people have heard of the standard auto_ptr smart pointer
facility, but not everyone uses it daily. That's a shame, because it
turns out that auto_ptr neatly solves common C++ design and coding
problems, and using it well can lead to more robust code." Herb
Sutter, 1999

"Avoid using auto_ptr, instead use shared_ptr which is widely
available and being added to the standard library." Herb Sutter,
2004.

Apparently he changed in the direction of _more_ smart pointers.
 
D

Duane Hebert

The standard containers do not require smart pointers, but using smart
pointers with the standard containers makes life much easier than using
the standard containers with raw pointers.


Not true. Raw pointers work fine, but are a sure recipe for leaks.

He's referring to the fact that std::auto_ptr isn't intended
for standard containers due to its copy semantics. Before
tr1, you had to use boost or some other implementation if you
wanted containers of smart pointers. This is no longer the
case with tr1.
 
R

red floyd

Stuart said:
Jim Langston said:
Someone made the statement in a newsgroup that most C++ programmers use
smart pointers. His actual phrase was "most of us" but I really don't
think that most C++ programmers use smart pointers, but I just don't know.

I don't like them because I don't trust them. I use new and delete on
pure pointers instead.

Do you use smart pointers?

[list redacted]

Good list Stu, but you left off what IMHO is one of the best reasons for
using smart pointers (even just auto_ptr, where appropriate): They make
it easier to write exception safe code.
 
R

Roland Pibinger

The above is a user problem, not a auto_ptr problem. The same as if
you just wrote 'delete &i;'

It's an auto_ptr problem because it violates a basic principle of the
Standard libraries (C and C++): don't delete (free) what you haven't
allocated. The same appplies to auto_ptr's 'destructive copy
semantics'.
In my opinion, auto_ptr should no longer be regarded as "the usual"
smart pointer, at least for new code. Boost::shared_ptr is my usual
smart pointer, with safer and more flexible behavior at the cost of
some comparatively very cheap memory and CPU cycles. tr1:: if you
have it.

What is 'safer' with shared_ptr. Does it check for NULL pointers
before dereferncing? Does it protect you against:
int i = 0;
shared_ptr<int> ap (&i);
Do 'custom deleters' relly enhance safety?
Is it appropriate for a 'pointer' class (template) which is intended
to replace real pointes to internally allocate a counter for each
pointed-to object? (Real pointes are ultra-lightweight objects, like
an int).

Best wishes,
Roland Pibinger
 
S

Stuart Golodetz

red floyd said:
Stuart said:
Jim Langston said:
Someone made the statement in a newsgroup that most C++ programmers use
smart pointers. His actual phrase was "most of us" but I really don't
think that most C++ programmers use smart pointers, but I just don't
know.

I don't like them because I don't trust them. I use new and delete on
pure pointers instead.

Do you use smart pointers?

[list redacted]

Good list Stu, but you left off what IMHO is one of the best reasons for
using smart pointers (even just auto_ptr, where appropriate): They make
it easier to write exception safe code.

:) To quote from my previous post, "* Making things exception-safe is harder
with raw pointers." I think I should have made it more visible, I squeezed
it in at the bottom of the list.

Regards,
Stu
 
R

Roland Pibinger

shared_ptr doesn't transfer
ownership, shared_ptr keeps ownership. That's exactly what Stroustrup
was promoting.

The only minor exception is during initialisation:

That's anything but 'minor'!
shared_ptr< some_t > ptr(new some_t(...));

But that's highly idiomatic.

Rather idiosyncratic than idiomatic (there is another word starting
with 'idio' that could be used here :)
Is this initialisation what the fuss is about?

If so, write a small wrapper

template< typename T > // this following for any number of params
shared_ptr< T > init_shared_ptr(T1 const& t1, T2 const& t2)
{
return shared_ptr< T >(new T(t1, t2));
}

and take shared_ptr and init_shared_ptr _together_ as a library that
confines ownership.

In general, you need ref-counting only when you _return_ 'ownership'
form a function (which is bad style anyway). In other cases
ref-counting is unnecessary. What would be the use of counting? When
you don't return ownership you know in advance when/where the
ref-counter drops to 0. It's the same scope in which you have created
the ref-counted object (disregarding contrived examples with static or
global ref-counted objects). Most examples of shared_ptr I have seen
so far don't need any ref-counting because they either don't return
ownership or the return of ownership can easily be avoided.

Best wishes,
Roland Pibinger
 
R

Roland Pibinger

The idea wasn't particuarly new then. Just for example, look toward the
end of:
http://tinyurl.com/nz6pf

It's not new but obviously not well known. IMO, the essence of 'real'
RAII (and the main reason for still using C++) is that it guarantees
both, automatic and deterministic (ie. scope bound) resource
management.

Best wishes,
Roland Pibinger
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,097
Latest member
RayE496148

Latest Threads

Top