Poll: Do you use smart pointers?

D

Dave Steffen

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.

"Nobody knows what most C++ developers do"

- Bjarne Stroustrup

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

This is just crazy, as most of the other replies in this thread
point out.
Do you use smart pointers?

Our main product is ~80k SLOC of highly mathematical C++; there's
not a bare pointer to be seen, except in the depths of some of the
math libraries (which are not for the faint of heart). We switched
from raw pointers to Boost's shared pointer a while back, and
haven't had a memory leak since. We rely on them completely, and
have _never_ had a problem.

The only good reason _not_ to use them AFAIK is the memory overhead
of the ref count (which can be mitigated in several ways) and the
run-time overhead of the extra redirection. We estimate that the
run-time penalty in our application for using smart pointers is
around 2%. We may, in the future, have to do something about this,
but it's unlikely.
 
T

Thomas J. Gritzan

Jim 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.

There are C++ programmers who use char* with null-terminated strings
everywhere and don't know, or don't want to use std::string. There are C++
programmers who don't use std::vector and the other containers for the same
reasons.
They likely don't use smart pointers.
I don't like them because I don't trust them. I use new and delete on pure
pointers instead.

I wrote my own string class and linked list class some years ago because I
didn't trust the standard library containers. It is a kind of "fear of the
unknown". Now I use the standard containers because I learned that they are
better designed and better implemented than my own implementations.

When I started reading this newsgroup, I learned about the boost library
and started using its classes as well, including the smart pointers.
Do you use smart pointers?

Yes.
 
P

peter koch

Howard said:
Kind of harsh isn't it, calling someone's personal opinion "absolute
rubbish"?
Right - it looks needlessly harsh, and was not intended as such (I hope
Jim Langston accepts my apologies). Still believing in your own code
and distrusting professional grade code from places such as boost is
foolish (but also very human!).

As for the questions I snipped below, they have been answered perfectly
by Tomas Tutone (if i remember correctly).

/Peter
[snip]
 
J

Jerry Coffin

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 think part of that depends somewhat on what you include as a smart
pointer. Would you, for example, include vector? One on hand, it doesn't
even attempt to act much like a pointer (e.g. it doesn't include a '->'
member) but at the same time, it really IS a wrapper around a pointer.
In fact, nearly all of the standard collection templates use pointers
internally, to at least some degree -- but most of them don't attempt to
imitate a pointer.

What most people call "smart pointer" I'd call "semi-smart pointers",
where most things like collection classes are "really smart pointers". A
typical smart pointer hides some of the ugliness of real pointers, but
most collection classes hide considerably more of it.
I don't like them because I don't trust them. I use new and delete on pure
pointers instead.

I'm sorry to hear that. Most of us did that (to some degree or other) at
one time, and there's little room for question that it's much more
difficult to write solid, dependable code this way.
Do you use smart pointers?

Personally, I make relatively little use of what most people class as
smart pointers, but a LOT of use of classes that wrap pointers
intelligently enough that there's little external evidence that what
you're dealing with is ultimately a pointer.
 
M

mlimber

Thomas said:
I wrote my own string class and linked list class some years ago because I
didn't trust the standard library containers. It is a kind of "fear of the
unknown". Now I use the standard containers because I learned that they are
better designed and better implemented than my own implementations.

The design of std::string (unlike most of the STL) is not the best, but
nonetheless, it is still almost always better than raw arrays or even
rolling your own string class.

Cheers! --M
 
D

Dave Steffen

Howard said:
Kind of harsh isn't it, calling someone's personal opinion "absolute
rubbish"?

Well, maybe, but my first response to your post was exactly the
same. I don't know of _any_ good reason not to use smart pointers,
except in cases where the overhead isn't acceptable; and I'll bet
money those cases are not only rare, but much more rare than most
people would think.
Also, don't the STL containers require smart pointers which are not
themselves found in the STL? It seems to me that things like
std::vector require using something like the Boost smart pointers.
I forget the reasoning exactly, but that's correct, isn't it? And
many of us don't have Boost, so what's the alternative?

Well, yes, STL containers-of-pointers are much better done as
containers-of-smart-pointers. And yes, the standard library
originally had only one kind of smart pointer, 'auto_ptr', which was
there for very specific purposes, and not suitable for use in std
containers.

You have two alternatives: the first is Boost, if you don't have it
then get it; things like smart pointers ("should" have been in the
standard library but weren't) is why Boost was started in the first
place.

Second, get a standard library that implements TR1, which
more-or-less took Boost's smart pointers and made 'em standard.
 
P

Peter

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

sorry to hear that.
Why not rely on compiler generated code instead?
Smart pointers are a necessary if you want to write exception safe
code.

Do you use smart pointers?

I usually use a smart pointer which relies on the pointed object to
provide Addref()/Release() methods. This has the advantage to the boost
smart pointer that one does not need an additional memory allocation
for the reference count object.
And one can create additional smart pointers from the raw pointer
without mistakes.
Usually I make the constructor private and provide a static method
which returns a smart pointer to the created object.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Jerry said:
What most people call "smart pointer" I'd call "semi-smart pointers",
where most things like collection classes are "really smart pointers".

I think is much clear to call the collections "collections" and "smart
pointers" things that are used like pointers, unless you want that most
people misunderstand what you say.
 
P

Phlip

Peter said:
Smart pointers are a necessary if you want to write exception safe
code.

By "necessary", you mean to rapidly write flexible code despite exceptions
and such.

Anyone can hard-code 'delete' calls all over the place. Not rapid or
flexible!!
 
P

Pete Becker

Phlip said:
Small smart pointers are the same size as pointers, and they insert opcodes
to call 'delete' into all the places where you should have coded 'delete'.
So their resource impact is minimal.

Well, I don't know what a "small smart pointer" would be, but TR1's
smart pointer (and Boost's, which it's based on) can be fairly expensive:

void f()
{
int *ip = new int(3);
delete ip;
}

void g()
{
std::tr1::shared_ptr<int> sp(new int(3));
}

The first function makes one allocation from the free store, asking for
sizeof(int) bytes. The second makes two allocations, one for sizeof(int)
bytes and one for however many bytes are needed for shared_ptr's control
block, which holds a reference count, a pointer, and perhaps another
pointer to a cleanup function (empty in this example). I don't consider
using four times as much memory to be minimal.

That's not to say that shared_ptr isn't useful, but it's not something
you should automatically use everywhere.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
M

mlimber

Pete said:
Well, I don't know what a "small smart pointer" would be, but TR1's
smart pointer (and Boost's, which it's based on) can be fairly expensive:

void f()
{
int *ip = new int(3);
delete ip;
}

void g()
{
std::tr1::shared_ptr<int> sp(new int(3));
}

The first function makes one allocation from the free store, asking for
sizeof(int) bytes. The second makes two allocations, one for sizeof(int)
bytes and one for however many bytes are needed for shared_ptr's control
block, which holds a reference count, a pointer, and perhaps another
pointer to a cleanup function (empty in this example). I don't consider
using four times as much memory to be minimal.

That's not to say that shared_ptr isn't useful, but it's not something
you should automatically use everywhere.

std::auto_ptr is such a "small smart pointer." It requires "essentially
no overhead" (TC++PL 14.4.2).

Cheers! --M
 
N

Noah Roberts

Pete said:
Well, I don't know what a "small smart pointer" would be, but TR1's
smart pointer (and Boost's, which it's based on) can be fairly expensive:

void f()
{
int *ip = new int(3);
delete ip;
}

void g()
{
std::tr1::shared_ptr<int> sp(new int(3));
}

shared_ptr is not the appropriate smart pointer for that use...
The first function makes one allocation from the free store, asking for
sizeof(int) bytes. The second makes two allocations, one for sizeof(int)
bytes and one for however many bytes are needed for shared_ptr's control
block, which holds a reference count, a pointer, and perhaps another
pointer to a cleanup function (empty in this example). I don't consider
using four times as much memory to be minimal.

....and that would be why.
That's not to say that shared_ptr isn't useful, but it's not something
you should automatically use everywhere.

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). You also
have auto_ptr at your disposal for cases like the above and
boost::scoped_ptr, which was made just for such situations, if you are
using boost.

A reference counting smart pointer is only one type of smart pointer
that serves a particular purpose. Just because your pointers are smart
doesn't mean you don't still have to be. Correct tools for the job and
all that...you wouldn't generalize the performance of all STL
containers based on a misuse of std::vector.

I know you know this but others might percieve what you are saying as
an argument against smart pointers and if it is it isn't a very good
one.
 
V

Victor Bazarov

Pete said:
Well, I don't know what a "small smart pointer" would be, but TR1's
smart pointer (and Boost's, which it's based on) can be fairly
expensive:
void f()
{
int *ip = new int(3);
delete ip;
}

void g()
{
std::tr1::shared_ptr<int> sp(new int(3));
}

The first function makes one allocation from the free store, asking
for sizeof(int) bytes. The second makes two allocations, one for
sizeof(int) bytes and one for however many bytes are needed for
shared_ptr's control block, which holds a reference count, a pointer,
and perhaps another pointer to a cleanup function (empty in this
example). I don't consider using four times as much memory to be
minimal.
That's not to say that shared_ptr isn't useful, but it's not something
you should automatically use everywhere.

Your example looks somewhat contrived, Pete. Who in their right mind
would allocate a single int from the free store? I don't mean to
question the need for small objects, I just don't think that this is
a valid example to prove the expensiveness of the smart pointer.

V
 
R

Roland Pibinger

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?

No! 'Smart' pointers are very unsmart.
You should have asked why someone would use 'smart' pointers. In fact,
the concept of 'smart' pointers is flawed in so many ways that I
amazed that some people still recommend them. The deficiencies are
well known: transfer of ownership, error-prone usage, inefficiency
(esp. for ref-counted s.p.).

Just say no to 'smart' pointers.
Roland Pibinger
 
S

Stuart Golodetz

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?

Yes, I do now. I always used to be of the opinion that you might as well use
raw pointers and avoid the overhead - after all, "real programmers don't let
their code leak". Ahem...well...that says maybe. On the other hand, with the
benefit of a bit more experience:

* Using raw pointers involves cognitive overhead that you can do without.
Your brain is best employed elsewhere.
* Unless smart pointers are significantly slower, you might as well be using
them. You can start with them, profile, and replace them with raw pointers
if necessary later on.
* You might be a "real programmer", whatever that is. All it takes is one
person on your team who isn't... It might even be you, if you're really
unlucky ("unreal"(?!) programmers don't often know it...). [Incidentally,
that wasn't directed at you. It was more a remark aimed at people who think
they're better at something than they are. It's an easy trap to fall into,
but best avoided.]
* Simplicity is a good thing. Manually keeping track of the places where you
need to use delete is not always as easy as it looks. (Yes, yes, we all know
that "real programmers laugh in the face of complexity". Why not *avoid*
complexity to the greatest extent possible instead? Or to take an analogy,
the ability to win a battle doesn't always mean you should fight it.)
* Making things exception-safe is harder with raw pointers.

Regards,
Stu
 
N

Noah Roberts

Roland said:
No! 'Smart' pointers are very unsmart.
You should have asked why someone would use 'smart' pointers. In fact,
the concept of 'smart' pointers is flawed in so many ways that I
amazed that some people still recommend them. The deficiencies are
well known: transfer of ownership, error-prone usage,

Interesting. Those are the exact weaknesses of raw pointers that smart
pointers avoid. Explain how you see them on the other side.
inefficiency
(esp. for ref-counted s.p.).

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? Since ref counted smart pointers are meant to aliviate
the difficulties associated with ownership semantics what is your raw
pointer alternative that is so much more efficient?
 
T

Thomas Tutone

Roland said:
No! 'Smart' pointers are very unsmart.
You should have asked why someone would use 'smart' pointers. In fact,
the concept of 'smart' pointers is flawed in so many ways that I
amazed that some people still recommend them. The deficiencies are
well known: transfer of ownership

True of std::auto_ptr 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.
error-prone usage,

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.
inefficiency
(esp. for ref-counted s.p.).

There's no point to using a reference-counted pointer where an auto_ptr
or weak_ptr would do the job, but if you have multiple pointers
pointing to the same object, keeping track of it all so that you delete
it at the proper time gets very complicated. I have yet to find a case
where the supposed marginal inefficiency of using a reference-counted
pointer in that situation had an effect that mattered. Have you
encountered such a case? Can you describe it please?
Just say no to 'smart' pointers.

I'm curious, Roland.

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?

Does your disdain for smart pointer extend to the entire RAII idiom, or
is it confined just to smart pointers?

My questions are not rhetorical - I believe that you are sincere in
your beliefs, and I am genuinely interested in your answers.

Best regards,

Tom
 
J

Jerry Coffin

[ ... use of smart pointers ]
No, it really is necessary in certain circumstances. See

http://www.gotw.ca/publications/xc++-auto_ptr.htm

Interestingly, this starts with the statement that: "Finally, auto_ptr
is sometimes essential to writing exception-safe code." The same
article, however, also says: "One way to solve the problem is to return
a pointer to a dynamically allocated String, but the best solution is to
go a step farther and return the pointer in an auto_ptr..."

IOW, it's self-contradictory: auto_ptr is really a convenience, NOT a
necessity as originally stated.

In this article, the challenge was to make this code strongly exception
safe:

String f()
{
String result;
result = "some value";
cout << "some output";
return result;
}

and the solution he gives is:

auto_ptr<String> f()
{
auto_ptr<String> result = new String;
*result = "some value";
cout << "some output";
return result;
// rely on transfer of
// ownership; this can't throw
}

But IMO, it would probably be better to use something like:

void f(String &result) {
String r;
r = "some value";
cout << "some output";
r.swap(result);
}

which is basically just hi-jacking the exception-safe assignment from
Item 13 of the same book, and using it to do an exception-safe
assignment of the return value. Of course, this requires that the String
class contain a swap that doesn't throw -- but as the aforementioned
Item 13 makes clear, you should almost certainly have that in any case.
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top