By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,910 Members | 1,085 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,910 IT Pros & Developers. It's quick & easy.

To use or not to use smart pointers?

P: n/a
I had a 3 hours meeting today with some fellow programmers that are partly
not convinced about using smart pointers in C++. Their main concern is a
possible performance impact. I've been explaining the advantages of smart
pointers endlessly (which are currently used in all our C++ software; we
use the Boost smart pointers) as I'm seriously concerned that there is a
shift to raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want to
write a C++ program without smart pointers any more but after that endless
discussion I wonder if I'm too strict. Any serious arguments not to use
smart pointers?

Boris
Jul 18 '07 #1
Share this Question
Share on Google+
54 Replies


P: n/a
Boris wrote:
I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact. I've been explaining the
advantages of smart pointers endlessly (which are currently used in
all our C++ software; we use the Boost smart pointers) as I'm
seriously concerned that there is a shift to raw pointers. We are not
developing system software but rather normal Windows programs (with
exceptions turned on). I wouldn't want to write a C++ program without
smart pointers any more but after that endless discussion I wonder if
I'm too strict. Any serious arguments not to use smart pointers?
There _is_ no performance impact. Whoever claims there is, should
prove it to you instead of just saying that. A smart pointer is just
a way for a programmer to relax and not have to remember when to
delete the object when the pointer goes out of scope. All access
to the actual object is resolved at compile time - no overhead.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 18 '07 #2

P: n/a

"Boris" <bo***@gtemail.netwrote in message
news:op***************@burk.mshome.net...
>I had a 3 hours meeting today with some fellow programmers that are partly
not convinced about using smart pointers in C++. Their main concern is a
possible performance impact. I've been explaining the advantages of smart
pointers endlessly (which are currently used in all our C++ software; we
use the Boost smart pointers) as I'm seriously concerned that there is a
shift to raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want to
write a C++ program without smart pointers any more but after that endless
discussion I wonder if I'm too strict. Any serious arguments not to use
smart pointers?
Oh my gosh, are you serious? No way. You are absolutely correct. The
benefits of smart pointers FAR outweigh any possible arguments against them.
There is no performance impact (that I know of), and the advantages
(automatic and correct object/resource lifetime management, avoidance of
memory leaks in the presence of exceptions, to name only two) are too
compelling to ignore. Another (strange, but typical) argument made against
smart pointers is their sometimes odd usage syntax (extra typing, ugliness?
I don't know), but in my view, that is a very small price to pay for the
peace of mind and safety afforded by their use.

If your collegues convince you otherwise, you should be working in another
field. If they won't listen to you about the benefits of smart pointers, go
work somewhere else where your position on the subject is appreciated (if
not required)!

- Dennis
Jul 18 '07 #3

P: n/a
On Wed, 18 Jul 2007 16:17:13 -0400, Victor Bazarov wrote:
Boris wrote:
>I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact. I've been explaining the
advantages of smart pointers endlessly (which are currently used in all
our C++ software; we use the Boost smart pointers) as I'm seriously
concerned that there is a shift to raw pointers. We are not developing
system software but rather normal Windows programs (with exceptions
turned on). I wouldn't want to write a C++ program without smart
pointers any more but after that endless discussion I wonder if I'm too
strict. Any serious arguments not to use smart pointers?

There _is_ no performance impact. Whoever claims there is, should prove
it to you instead of just saying that. A smart pointer is just a way
for a programmer to relax and not have to remember when to delete the
object when the pointer goes out of scope. All access to the actual
object is resolved at compile time - no overhead.
boost::shared_ptr (or std::tr1::shared_ptr if you prefer) has a
significant performance overhead especially when being copied. There are
benchmarks at www.boost.org and I have also measured this myself.

The reasons are fairly obvious:

1. A boost::shared_ptr is larger than a plain pointer. It basically holds
two pointers -- one to the actual object the other to the reference
counter.
2. The reference counter needs to be incremented/decremented when the
smart pointer is copied/destroyed.
3. Locking is required to manipulate the reference counter for thread
safety.

Whether this all makes a difference in a given application is far from
obvious. I have switched an application that was extensively using a tree
structure built using boost::shared_ptr to boost::intrusive_ptr with a
significant performance gain.

--
Markus Schoder
Jul 18 '07 #4

P: n/a
Boris <bo***@gtemail.netwrote:
I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact.
If they find an *actual* performance impact, then they have a leg to
stand on, until then their appeal to fear is fallacious.
I've been explaining the advantages of smart pointers endlessly
(which are currently used in all our C++ software; we use the Boost
smart pointers) as I'm seriously concerned that there is a shift to
raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but after
that endless discussion I wonder if I'm too strict.
Why on earth would you want to write the same pointer management code
over, and over again? That's not reuse... Do these fellows also write a
loop instead of using strcpy? (I've known programmers who do that.)
Any serious arguments not to use smart pointers?
"The boss will yell at you and make you remove them."
Jul 18 '07 #5

P: n/a
Victor Bazarov wrote:
Boris wrote:
>I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact. I've been explaining the
advantages of smart pointers endlessly (which are currently used in
all our C++ software; we use the Boost smart pointers) as I'm
seriously concerned that there is a shift to raw pointers. We are not
developing system software but rather normal Windows programs (with
exceptions turned on). I wouldn't want to write a C++ program without
smart pointers any more but after that endless discussion I wonder if
I'm too strict. Any serious arguments not to use smart pointers?

There _is_ no performance impact. Whoever claims there is, should
prove it to you instead of just saying that. A smart pointer is just
a way for a programmer to relax and not have to remember when to
delete the object when the pointer goes out of scope. All access
to the actual object is resolved at compile time - no overhead.
With tr1::shared_ptr<>, I observed that the size of the smart pointer object
is twice as large as the size of a raw pointer (for two implementations, I
know). I actually doubt that one could to better and still have support for
the xxx_pointer_cast<templates.

Although dereferencing is just as efficient as with raw pointers, you can
have an overhead in space; and you should expect an overhead in assignment
and copy operations that results from updating the reference count.

That said, I would doubt that the difference shows in measurements. I agree
that the person arguing in favor of raw pointers has the burden of proof
(and also should carry the burden of proving the correctness for the code
base resulting from a design decision in favor of raw pointers).
Best

Kai-Uwe Bux
Jul 18 '07 #6

P: n/a
"Victor Bazarov" <v.********@comAcast.netwrites:
Boris wrote:
I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact
[...]
>
There _is_ no performance impact. Whoever claims there is, should
prove it to you instead of just saying that. A smart pointer is
just a way for a programmer to relax and not have to remember when
to delete the object when the pointer goes out of scope. All access
to the actual object is resolved at compile time - no overhead.
And by the way, I verified this experimentally last week while
profiling some code. Using GCC 4.0.4 and Boost 1.33.1, it looks like
there's a very small amount of overhead (like 5%) in executables built
in "debug" mode, e.g. no optimization, no inlining, etc. This
overhead *completely* dissapears when the optimization levels are turned
up.

So:

A) Even if there is some small performance impact, it's well worth
the *programmer* time you save developing and debugging your
code;

B) There isn't any performance impact when building executables for
real use, just as Victor says; and

C) This is easy to prove, so you don't have to take our word for it;
go do the experiment on your machine, with your compiler.

And by the way, we use smart pointers *everywhere*, and it's probably
saved us *years* of programmer time.

--
Dave Steffen, Ph.D. "I say we invite opportunity inside
Software Engineer IV for a nice cup of tea, then hit her
Numerica Corporation on the head and steal her purse."
ph (970) 461-2000 x227
dgsteffen numerica us -- Shlock Mercenary
Jul 18 '07 #7

P: n/a
* Dennis Jones:
There is no performance impact (that I know of), and the advantages
(automatic and correct object/resource lifetime management,
Automatic? Yes. Correct ? In your wildest dreams.
If your collegues convince you otherwise, you should be working in another
field. If they won't listen to you about the benefits of smart pointers, go
work somewhere else where your position on the subject is appreciated (if
not required)!
I really don't know what gave you the right to speak so harshly without even
remotely knowing the context. Boost::shared_ptr (or boost::whatever) is
_NOT_ the holy grail, and most definately NOT always applicable.

--
Martijn van Buul - pi**@dohd.org
Jul 18 '07 #8

P: n/a

"Martijn van Buul" <pi**@dohd.orgwrote in message
news:sl******************@mud.stack.nl...
>* Dennis Jones:
>There is no performance impact (that I know of), and the advantages
(automatic and correct object/resource lifetime management,

Automatic? Yes. Correct ? In your wildest dreams.
Okay, how about when used correctly?

>If your collegues convince you otherwise, you should be working in
another
field. If they won't listen to you about the benefits of smart pointers,
go
work somewhere else where your position on the subject is appreciated (if
not required)!

I really don't know what gave you the right to speak so harshly without
even
remotely knowing the context. Boost::shared_ptr (or boost::whatever) is
_NOT_ the holy grail, and most definately NOT always applicable.
I certainly didn't mean to be "harsh." I just find it hard to justify NOT
using them for any reason. I have personally developed an application that
has benefited greatly from using smart pointers almost (if not completely)
exclusively, which would have been a nightmare to develop and maintain
otherwise. And for me, that's enough of a reason to be a strong proponent.

I'm not an expert, for sure, but I can't think of a case where they would
not be applicable. Care to enlighten the unenlightened?

- Dennis
Jul 18 '07 #9

P: n/a
* Dennis Jones:
I'm not an expert, for sure, but I can't think of a case where they would
not be applicable. Care to enlighten the unenlightened?
I work in computer vision. Not too long ago, I was rewriting some of our
existing codebase. The algorithms itself were OK, but the implementation was
"C with classes" and no longer up to par.

One stood out in particular: A simple data structure used to identify objects
in a bitmap image, consisting of a doubly linked list of begin- and end points
for each row. This particular algorithm identified all connected objects in a
structure like this, and the existing implementation used a pool of these
critters, and was reasonably fast. ~ 200 microseconds per image, on my
computer, with my test set. (Using the same CPU and same compiler (gcc 4.2.0)
for all cases)

I first rewrote it to a std::list<CSegment>, with CSegment being something
like

struct CSegment
{
int mStart;
int mEnd;
int mRow;
};

Performance was abysmal; execution time went up to a staggering 50 ms. That's
more than the total budget I have for the *entire* evaluation process per
image, so it's not even close to acceptable.

I then rewrote it to a smart_ptr approach, by giving each CSegment a

boost::shared_ptr<CSegmentmNext
boost::weak_ptr<CSegmentmPrev

The reasoning behind this was that I *know* std::list does more checking
than I really needed, but I would like to have the protection against
memory leaks.

Performance dropped slightly, but not enough (40 ms). Not even close.

I then rewrote things to a plain jane new/delete fest, using normal
pointers. Execution time went down to 20 ms. Using a class-specific operator
new/delete, which used manually operated storage, took it down to 2 ms.
Ditching the operator new/delete, and using inline routines to do allocation
/release of segments got it down to its original 200 us. Inspection of the
resulting assembly yielded that it would save about two calls per allocation/
release.

So there you have it. boost::shared_ptr sucks for this application.
std::list sucks for this application. Nifty C++ like overloading operator new
is not good enough. The difference between "50 ms" and "200 us" is the
difference between "No product" and "something we can make profit out of".

Does this mean that boost::shared_ptr (or std::list, or... ) is bad? Hell no.
It works great, and can lead to very nice and elegant solutions. Claiming that
boost::shared_ptr should be avoided just because of situations like this
is plain stupid - exactly as stupid as asserting boost::shared_ptr is
better than using new/delete in each and every case.

Real life isn't that simple.
--
Martijn van Buul - pi**@dohd.org
Jul 19 '07 #10

P: n/a
* Victor Bazarov:
A smart pointer is just a way for a programmer to relax and not have to
remember when to delete the object when the pointer goes out of scope.
If a programmer wants to relax and don't bother to think about how his/her
code is going to work out, then _by all means_ go have a holiday.

--
Martijn van Buul - pi**@dohd.org
Jul 19 '07 #11

P: n/a
On 18 Jul 2007 21:09:26 GMT, Markus Schoder wrote:
>boost::shared_ptr (or std::tr1::shared_ptr if you prefer) has a
significant performance overhead especially when being copied. There are
benchmarks at www.boost.org and I have also measured this myself.

The reasons are fairly obvious:

1. A boost::shared_ptr is larger than a plain pointer. It basically holds
two pointers -- one to the actual object the other to the reference
counter.
2. The reference counter needs to be incremented/decremented when the
smart pointer is copied/destroyed.
3. Locking is required to manipulate the reference counter for thread
safety.
4. The reference counter of shared_ptr must be dynamically allocated.
This means one extra dynamic allocation for each pointed-to object.

5. 'Smart pointers' introduce semantic anomalies, e.g. auto_ptr uses
'destructive copy semantics'. 'Smart pointers' cannot completely
emulate real pointer behavior.

6. 'Smart pointers' foster a heap-oriented programming style ('Java in
C++').

In sum, the disadvantages of 'smart pointers' by far outweigh their
advantages.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 19 '07 #12

P: n/a
Roland Pibinger a écrit :
On 18 Jul 2007 21:09:26 GMT, Markus Schoder wrote:
>boost::shared_ptr (or std::tr1::shared_ptr if you prefer) has a
significant performance overhead especially when being copied. There are
benchmarks at www.boost.org and I have also measured this myself.

The reasons are fairly obvious:

1. A boost::shared_ptr is larger than a plain pointer. It basically holds
two pointers -- one to the actual object the other to the reference
counter.
2. The reference counter needs to be incremented/decremented when the
smart pointer is copied/destroyed.
3. Locking is required to manipulate the reference counter for thread
safety.

4. The reference counter of shared_ptr must be dynamically allocated.
This means one extra dynamic allocation for each pointed-to object.
Use boost::intrusive_ptr.
>
5. 'Smart pointers' introduce semantic anomalies, e.g. auto_ptr uses
'destructive copy semantics'. 'Smart pointers' cannot completely
emulate real pointer behavior.
use boost::scoped_ptr instead of auto_ptr to avoid the copy problem.
>
6. 'Smart pointers' foster a heap-oriented programming style ('Java in
C++').
You mean 'shared_ptr' foster ...
auto_ptr, scoped_ptr and intrusive_ptr are on the stack.
>
In sum, the disadvantages of 'smart pointers' by far outweigh their
advantages.
That depends. If what you need is reference counting (shared_ptr) then
any other reference counting system you may use will fare more or less
the same. The alternatives are :
- tracking down the livetime of object
- using garbage collecting

If you don't need it and just want to insure your pointer is destroyed
when going out of scope, use boost::scoped_ptr or std::auto_ptr (with
cautions) and then the performance overhead should be minimal.

Michael
Jul 19 '07 #13

P: n/a
Daniel T. a écrit :
Boris <bo***@gtemail.netwrote:
>I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact.

If they find an *actual* performance impact, then they have a leg to
stand on, until then their appeal to fear is fallacious.
>I've been explaining the advantages of smart pointers endlessly
(which are currently used in all our C++ software; we use the Boost
smart pointers) as I'm seriously concerned that there is a shift to
raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but after
that endless discussion I wonder if I'm too strict.

Why on earth would you want to write the same pointer management code
over, and over again? That's not reuse... Do these fellows also write a
loop instead of using strcpy? (I've known programmers who do that.)
>Any serious arguments not to use smart pointers?

"The boss will yell at you and make you remove them."
That reminded me of an ACCU article about developpers, monkeys and
cultural transmission:
http://accu.org/index.php/journals/290

This article could help as a starter for exception safety through smart
pointers:
http://accu.org/index.php/journals/298

Michael
Jul 19 '07 #14

P: n/a
On Thu, 19 Jul 2007 12:36:37 +0200, Michael DOUBEZ wrote:
>Roland Pibinger a écrit :
>4. The reference counter of shared_ptr must be dynamically allocated.
This means one extra dynamic allocation for each pointed-to object.

Use boost::intrusive_ptr.
I prefer non-intrusive, zero-overhead real pointers. Why accept
anything less?
>5. 'Smart pointers' introduce semantic anomalies, e.g. auto_ptr uses
'destructive copy semantics'. 'Smart pointers' cannot completely
emulate real pointer behavior.

use boost::scoped_ptr instead of auto_ptr to avoid the copy problem.
I prefer objects on the stack. Like many other 'smart pointers'
scoped_ptr is a solution desperately looking for a problem.
>6. 'Smart pointers' foster a heap-oriented programming style ('Java in
C++').

You mean 'shared_ptr' foster ...
auto_ptr, scoped_ptr and intrusive_ptr are on the stack.
But the pointed-to objects are not. The urge to use 'smart pointers'
typically pops up when (pointers to) objects shall be returned from a
function. This 'factory style' is characteristic for Java programming
and contrasts with RAII style of programming in C++ that binds
resources to one scope.
>The alternatives are :
- tracking down the livetime of object
- using garbage collecting
The alternative is RAII. Let a local object manage both, acquisition
and release of (a) resource(s).
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 19 '07 #15

P: n/a
Roland Pibinger a écrit :
On Thu, 19 Jul 2007 12:36:37 +0200, Michael DOUBEZ wrote:
>Roland Pibinger a écrit :
>>4. The reference counter of shared_ptr must be dynamically allocated.
This means one extra dynamic allocation for each pointed-to object.
Use boost::intrusive_ptr.

I prefer non-intrusive, zero-overhead real pointers. Why accept
anything less?
If that fits your need, doesn't cause ressource leak and make the code
clear. No reason.

Not everybody needs reference counting.
>
>>5. 'Smart pointers' introduce semantic anomalies, e.g. auto_ptr uses
'destructive copy semantics'. 'Smart pointers' cannot completely
emulate real pointer behavior.
use boost::scoped_ptr instead of auto_ptr to avoid the copy problem.

I prefer objects on the stack. Like many other 'smart pointers'
scoped_ptr is a solution desperately looking for a problem.
I also prefer object on the stack but when you cannot have them on the
stack which can hapen in non-functionnal-style programming or under
specific environment (cooperative OS by example).
>>6. 'Smart pointers' foster a heap-oriented programming style ('Java in
C++').
You mean 'shared_ptr' foster ...
auto_ptr, scoped_ptr and intrusive_ptr are on the stack.

But the pointed-to objects are not.
Then why do you need smart pointers ? Indeed, if the objects are on the
stack, do not use smart pointers and even why use pointer at all except
for function calls requiring a pointer.
The urge to use 'smart pointers'
typically pops up when (pointers to) objects shall be returned from a
function.
Strong exception guaranty is a good reason. Confidence (i.e. let the
compiler destroy my dynamically allocated pointer for me in my class) is
another. And in some case, it is hard to determine/track who should be
the owner of a ressource.
This 'factory style' is characteristic for Java programming
and contrasts with RAII style of programming in C++ that binds
resources to one scope.
Factory may be misused/overused as any other pattern but is still useful
even in C++.
>The alternatives are :
- tracking down the livetime of object
- using garbage collecting

The alternative is RAII. Let a local object manage both, acquisition
and release of (a) resource(s).
Do you advocate to create a specific RAII class for each ressource you
define ? I do no find it practical when a simple boost::scoped_ptr(new
Object()); do it for me.

Michael
Jul 19 '07 #16

P: n/a
On Jul 18, 1:17 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Boris wrote:
I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact. I've been explaining the
There _is_ no performance impact. Whoever claims there is, should
prove it to you instead of just saying that.
Not true! All the refcounting has a real cost. It doesn't stop me
from using them everywhere, though I have some other slight gripes
about them.

Jul 19 '07 #17

P: n/a
Michael DOUBEZ <mi************@free.frwrote:
Daniel T. a écrit :
Boris <bo***@gtemail.netwrote:
Any serious arguments not to use smart pointers?
"The boss will yell at you and make you remove them."

This article could help as a starter for exception safety through smart
pointers:
http://accu.org/index.php/journals/298
I live in an exception free world right now. But even then, smart
pointers are a nice way to reuse code.
Jul 19 '07 #18

P: n/a
Michael DOUBEZ wrote:
Daniel T. a écrit :
>Boris <bo***@gtemail.netwrote:
>>I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact.

If they find an *actual* performance impact, then they have a leg to
stand on, until then their appeal to fear is fallacious.
Just because you have difficulty measuring it doesn't mean it
doesn't exist. Most projects overuse shared_ptr<>. You need to
use an appropriate mix of auto_ptr<and shared_ptr<>.

std::auto_ptr<has no performance overhead, but
boost::share_ptr<necessarily internally needs a
synchronization object or interlocked increment. In a
multi-core CPU environment the lock or interlocked increment
operation requires the processor cache to be flushed so that the
change is visible to other cores. This performance hit can be
difficult to detect because no profiler outside of a hardware
logic analyzer can really detect it. You'll need to compare
performance with raw pointer code for the same tasks.

Despite this peanut butter spread of a performance penalty,
you'd be insane to use raw pointers. If you habitually use raw
pointers you might as well be programming in C. Used
appropriately, auto_ptr<>, shared_ptr<>, weak_ptr<>, and
brethren will eliminate all resource leaks and their attendant
problems such as memory corruption through premature frees. Raw
unwrapped pointers provide no protection. Naked pointers are
obscene.
>>
>>I've been explaining the advantages of smart pointers endlessly
(which are currently used in all our C++ software; we use the Boost
smart pointers) as I'm seriously concerned that there is a shift to
raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but after
that endless discussion I wonder if I'm too strict.

Why on earth would you want to write the same pointer management code
over, and over again? That's not reuse... Do these fellows also write
a loop instead of using strcpy? (I've known programmers who do that.)
>>Any serious arguments not to use smart pointers?

"The boss will yell at you and make you remove them."

That reminded me of an ACCU article about developpers, monkeys and
cultural transmission:
http://accu.org/index.php/journals/290

This article could help as a starter for exception safety through smart
pointers:
http://accu.org/index.php/journals/298

Michael
Rather than habitually using shared_ptr<>, consider using the
boost smart containers. Use auto_ptr<as much as possible to
avoid sharing. Consider that shared objects are another form of
global information that violates encapsulation in the time
domain. Use shared_ptr<when you need to but use auto_ptr<>
when you really mean to transfer ownership.

Glen
Jul 19 '07 #19

P: n/a

"Martijn van Buul" <pi**@dohd.orgwrote in message
news:sl******************@mud.stack.nl...
So there you have it. boost::shared_ptr sucks for this application.
std::list sucks for this application. Nifty C++ like overloading operator
new
is not good enough. The difference between "50 ms" and "200 us" is the
difference between "No product" and "something we can make profit out of".

Does this mean that boost::shared_ptr (or std::list, or... ) is bad? Hell
no.
It works great, and can lead to very nice and elegant solutions. Claiming
that
boost::shared_ptr should be avoided just because of situations like this
is plain stupid - exactly as stupid as asserting boost::shared_ptr is
better than using new/delete in each and every case.
I see. Thanks for sharing that. I had no idea performance could be so
negatively affected. Thankfully, my application is not nearly as affected
by the performance penalties you site. While it needs to perform well, my
application doesn't allocate that much memory, and its performance
requirements are not even close to what yours apparently are. Also, I only
use shared_ptr when I need it for its reference counting ability (and
sometimes for the custom deleter, and in those cases, performance isn't even
an issue). Otherwise I use the much simpler scoped_ptr.

- Dennis
Jul 19 '07 #20

P: n/a
Martijn van Buul <pi**@dohd.orgwrote:
* Dennis Jones:
I'm not an expert, for sure, but I can't think of a case where they would
not be applicable. Care to enlighten the unenlightened?

I work in computer vision. Not too long ago, I was rewriting some of our
existing codebase. The algorithms itself were OK, but the implementation was
"C with classes" and no longer up to par.
[Anecdote snipped]

If we are going down that road. I worked with someone who insisted on
writing his own double-linked list code because "there is no way generic
code could be faster". It turned out that std::list was a full 5% faster
than anything he could come up with with full optimizations on.
(However, it was much slower without optimization.) And the program was
much easer to write and understand.
Jul 20 '07 #21

P: n/a
Daniel T. a écrit :
Martijn van Buul <pi**@dohd.orgwrote:
>* Dennis Jones:
>>I'm not an expert, for sure, but I can't think of a case where they would
not be applicable. Care to enlighten the unenlightened?
I work in computer vision. Not too long ago, I was rewriting some of our
existing codebase. The algorithms itself were OK, but the implementation was
"C with classes" and no longer up to par.

[Anecdote snipped]

If we are going down that road. I worked with someone who insisted on
writing his own double-linked list code because "there is no way generic
code could be faster". It turned out that std::list was a full 5% faster
than anything he could come up with with full optimizations on.
(However, it was much slower without optimization.) And the program was
much easer to write and understand.
In the specific case of Martijn van Buul, I expect a pool allocator
would have been indicated; that depends on the rate at which elements
were inserted/removed from the list. If it is intensive, calling a heap
allocator each time is a killer.

Michael

Jul 20 '07 #22

P: n/a
* Michael DOUBEZ:
In the specific case of Martijn van Buul, I expect a pool allocator
would have been indicated; that depends on the rate at which elements
were inserted/removed from the list. If it is intensive, calling a heap
allocator each time is a killer.
I used a pool allocator, and that helped *some*. Just not enough. Sometimes,
you cannot dismiss the overhead of an extra call, or an extra indirection, as
being irrelevant.

--
Martijn van Buul - pi**@dohd.org
Jul 20 '07 #23

P: n/a
Martijn van Buul a écrit :
* Michael DOUBEZ:
>In the specific case of Martijn van Buul, I expect a pool allocator
would have been indicated; that depends on the rate at which elements
were inserted/removed from the list. If it is intensive, calling a heap
allocator each time is a killer.

I used a pool allocator, and that helped *some*. Just not enough. Sometimes,
you cannot dismiss the overhead of an extra call, or an extra indirection, as
being irrelevant.
I don't see where you would have an extra indirection and the extra call
depends on the compiler (and somewhat the STL implementation used).
If your benchmark showed you not to use STL on your plateform, then you
were right not to but that doesn't mean it is a general flaw.

Michael

Jul 20 '07 #24

P: n/a
In article <sl******************@mud.stack.nl>,
Martijn van Buul <pi****************@dohd.orgwrote:
>* Dennis Jones:
>I'm not an expert, for sure, but I can't think of a case where they would
not be applicable. Care to enlighten the unenlightened?

One stood out in particular: A simple data structure used to identify objects
in a bitmap image, consisting of a doubly linked list of begin- and end points
for each row. This particular algorithm identified all connected objects in a
structure like this, and the existing implementation used a pool of these
critters, and was reasonably fast. ~ 200 microseconds per image, on my
computer, with my test set. (Using the same CPU and same compiler (gcc 4.2.0)
for all cases)

I first rewrote it to a std::list<CSegment>, with CSegment being something
like

struct CSegment
{
int mStart;
int mEnd;
int mRow;
};

Performance was abysmal; execution time went up to a staggering 50 ms. That's
more than the total budget I have for the *entire* evaluation process per
image, so it's not even close to acceptable.
I am assuming that you have used an optimized STL. Speed differences
between a non-opimtised STL and an optimised one can huge.

The other point I would have looked at is if the std::list was the
correct container for your application. Although it might be tempting
to replace a linked list with a std::list, quite often, a std::vector
is more appropriate. The speed characteristics of a list vs vecotr
are different and unless you need fast splicing and/or
insertion/delition in the middle, a vector might be better or maybe a
deque.

See for example this article:
http://www.ddj.com/dept/cpp/184401838

Yan

Jul 20 '07 #25

P: n/a
On Jul 19, 9:40 am, Glen Dayton <REMOVEday...@ieee.orgwrote:
multi-core CPU environment the lock or interlocked increment
operation requires the processor cache to be flushed so that the
Not strictly true - a cache flush is a heavy handed way to handle
atomic ops. Most platforms have better soluttions, such as robust
cache-cohenerncy protocols. It still has a (large) cost, but not as
much as a full cache flush, and usually not even as much as a full
line flush.
change is visible to other cores. This performance hit can be
difficult to detect because no profiler outside of a hardware
logic analyzer can really detect it. You'll need to compare
performance with raw pointer code for the same tasks.
valgrind !!
Despite this peanut butter spread of a performance penalty,
you'd be insane to use raw pointers. If you habitually use raw
pointers you might as well be programming in C. Used
appropriately, auto_ptr<>, shared_ptr<>, weak_ptr<>, and
brethren will eliminate all resource leaks and their attendant
problems such as memory corruption through premature frees. Raw
unwrapped pointers provide no protection. Naked pointers are
obscene.
I can't agree with these superlatives - there is no silver bullet.
Nothing solves every problem. Smart pointers can help solve a lot of
problems, but be realistic, please :)

Tim
Jul 20 '07 #26

P: n/a
I had a 3 hours meeting today with some fellow programmers
that are partly not convinced about using smart pointers in
C++.
Does that mean that they are convinced that one should never use
them, or that they are convinced that they aren't a silver
bullet, and should only be used where appropriate (which isn't
really all that often).
Their main concern is a possible performance impact.
Obviously, there is some effect, but you have to compare it to
the alternatives, in your application.

The few actual benchmarks I know show the Boehm collector to be
significantly faster than boost::shared_ptr. But as much as I
also favor using the Boehm collector, I do recognize that they
were written by people who strongly favor garbage collection,
and that they intentionally chose scenarios where the difference
would be significant. I suspect that in most applications,
garbage collection will be slightly faster, but the difference
won't be significant.
I've been explaining the advantages of smart pointers
endlessly (which are currently used in all our C++ software;
we use the Boost smart pointers) as I'm seriously concerned
that there is a shift to raw pointers.
That's interesting. I've always found that trying to use them
systematically (rather than just in specific cases) caused a lot
of extra effort for no gain.
We are not developing system software but rather normal
Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but
after that endless discussion I wonder if I'm too strict. Any
serious arguments not to use smart pointers?
Not to use them in the occasional cases where they are
appropriate, none. But that's true for a lot of things.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 20 '07 #27

P: n/a
On Jul 18, 11:02 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:

[...]
(and also should carry the burden of proving the correctness
for the code base resulting from a design decision in favor of
raw pointers).
That is, of course, the key part. Systematic use of shared_ptr,
where not appropriate, makes it very difficult to prove that the
code is correct.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 20 '07 #28

P: n/a
On Jul 18, 11:16 pm, Dave Steffen <dgstef...@numerica.uswrote:
"Victor Bazarov" <v.Abaza...@comAcast.netwrites:
Boris wrote:
I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact
[...]
There _is_ no performance impact. Whoever claims there is, should
prove it to you instead of just saying that. A smart pointer is
just a way for a programmer to relax and not have to remember when
to delete the object when the pointer goes out of scope. All access
to the actual object is resolved at compile time - no overhead.
And by the way, I verified this experimentally last week while
profiling some code. Using GCC 4.0.4 and Boost 1.33.1, it
looks like there's a very small amount of overhead (like 5%)
in executables built in "debug" mode, e.g. no optimization, no
inlining, etc. This overhead *completely* dissapears when the
optimization levels are turned up.
You really should publish your benchmarks, then, because this is
in contradiction with all published benchmarks. (It's also in
contradiction with common sense, of course, but I'm very
suspicious of common sense when it comes to performance.)

In practice, I doubt that there will be a significant difference
in very many applications, although it should be possible to
create artificial cases that strongly favor one or the other.
The real difference is program correctness---boost::shared_ptr
makes it very difficult to reason about program correctness
except in specific cases.

[...]
C) This is easy to prove, so you don't have to take our word for it;
go do the experiment on your machine, with your compiler.
And code typical for your application.
And by the way, we use smart pointers *everywhere*, and it's probably
saved us *years* of programmer time.
Compared to what? It sounds like a lot of extra work for
nothing. (Actually, it sounds like the claim from people using
Java, that memory leaks are impossible with garbage collection.
Both shared_ptr and garbage collection are very powerful tools
for specific cases---garbage collection is more generally
applicable than shared_ptr---but neither is a silver bullet.)

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 20 '07 #29

P: n/a
On Jul 18, 11:13 pm, "Daniel T." <danie...@earthlink.netwrote:
Boris <bo...@gtemail.netwrote:
I had a 3 hours meeting today with some fellow programmers that are
partly not convinced about using smart pointers in C++. Their main
concern is a possible performance impact.
If they find an *actual* performance impact, then they have a leg to
stand on, until then their appeal to fear is fallacious.
There are already a significant number of benchmarks which show
a real impact.
I've been explaining the advantages of smart pointers endlessly
(which are currently used in all our C++ software; we use the Boost
smart pointers) as I'm seriously concerned that there is a shift to
raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but after
that endless discussion I wonder if I'm too strict.
Why on earth would you want to write the same pointer management code
over, and over again?
What is there to manage about a pointer? A pointer is just a
means of navigating between objects. (And since navigational
possibilities almost always includes cycles, using smart
pointers, instead of raw pointers, requires additional analysis,
and introduces significant additional possibilities for errors.)

If you're talking about lifetime management, of course, the
reason why you rewrite it each time is because the the only
objects you allocate dynamically in C++ are those which require
explicit, application specific lifetime management, which is
different each time.
That's not reuse... Do these fellows also write a
loop instead of using strcpy? (I've known programmers who do that.)
Any serious arguments not to use smart pointers?
"The boss will yell at you and make you remove them."
You want your program to work correctly, and not leak memory.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jul 20 '07 #30

P: n/a
On Jul 19, 6:40 pm, Glen Dayton <REMOVEday...@ieee.orgwrote:

[...]
Despite this peanut butter spread of a performance penalty,
you'd be insane to use raw pointers.
So you consider smart pointers a silver bullet. Despite the
significant extra effort it takes to use them, and the fact that
they don't solve anything most of the time, but rather introduce
new problems (like managing cycles) which weren't there before
hand.
If you habitually use raw pointers you might as well be
programming in C.
In other words, you don't have any real arguments, so you resort
to name calling.
Used
appropriately, auto_ptr<>, shared_ptr<>, weak_ptr<>, and
brethren will eliminate all resource leaks and their attendant
problems such as memory corruption through premature frees.
So once again, you're claiming a silver bullet. Oh how I wish
it were true. I've worked a lot on applications which run 24
hours a day, 7 days a wekk, where we have contractual penalties
for down time. You can't depend on smart pointers there.
Raw unwrapped pointers provide no protection.
Nor do they provide any added problems when all you want to do
is navigate (and not manage lifetime), or when the lifetime
depends on the application logic.
Naked pointers are obscene.
More name calling, in the absense of any real arguments.
>I've been explaining the advantages of smart pointers endlessly
(which are currently used in all our C++ software; we use the Boost
smart pointers) as I'm seriously concerned that there is a shift to
raw pointers. We are not developing system software but rather
normal Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but after
that endless discussion I wonder if I'm too strict.
Why on earth would you want to write the same pointer management code
over, and over again? That's not reuse... Do these fellows also write
a loop instead of using strcpy? (I've known programmers who do that.)
>Any serious arguments not to use smart pointers?
"The boss will yell at you and make you remove them."
That reminded me of an ACCU article about developpers, monkeys and
cultural transmission:
http://accu.org/index.php/journals/290
This article could help as a starter for exception safety through smart
pointers:
http://accu.org/index.php/journals/298
Rather than habitually using shared_ptr<>, consider using the
boost smart containers. Use auto_ptr<as much as possible to
avoid sharing.
auto_ptr<plays a very important roll in thread safety. You
use auto_ptr<in your message passing interfaces, and you're
guaranteed that the sending thread will not try to access the object
when it is in possession of the receiving thread. The
advantages are enough to outweigh the disadvantage of its
preempting lifetime management (and "messages" typically don't
have to have an explicit lifetime anyway).

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 20 '07 #31

P: n/a
James Kanze wrote:
On Jul 18, 11:02 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:

[...]
>(and also should carry the burden of proving the correctness
for the code base resulting from a design decision in favor of
raw pointers).

That is, of course, the key part. Systematic use of shared_ptr,
where not appropriate, makes it very difficult to prove that the
code is correct.
Pointers in C++ are heavily overloaded. They offer two main
features at once, namely (a) decoupling life-time from scope
and (b) support for polymorphism. If you want the later, you
are inviting upon you the perrils of the former.

That pointer and pointee have different life-times introduces
a global state into the program and arguing correctness becomes
much more of a hassle: every new() has to match with one and
only one delete() along each path of execution. Exceptions can
divert the execution path at any moment to an unknown location,
and client supplied types in templates make it unpredictable
what will throw and what will be thrown. That makes life very
hard.

A smart pointer like shared_ptr<also requires global
knowledge in at least two ways: (a) we need to ensure that
no cycles occur and (b) when one relies on side-effects of
a destructor, sometimes one needs to argue that the last
pointer owning a given pointee is going out of scope.

For me, the lesson is that one needs a set of idioms and tools
that allow us to reduce code complexity and restore the ability
to argue correctness of code locally (by looking at, say, 20
_consecutive_ lines of code at a time). Thus, I tend to wrap
pointers within classes. Smart pointers are just readily packaged
idioms that come up often in this context. For these reasons, smart
pointers form an intermediate layer in my library. They are used
to build other components but rarely used directly. Let me
illustrate this with a few examples.
Example 1 [statefull function objects]
=========

The standard algorithms take function objects by value
and (with the notable exception of for_each) are allowed
to copy those object around. Thus, I found something like
this usefull at times:

template < typename Func >
class unary_f_ref
: std::unary_function< typename Func::argument_type,
typename Func::result_type >
{

std::tr1::shared_ptr<Functhe_func;

public:

unary_f_ref ( Func const & f )
: the_func ( new Func ( f ) )
{}

typename Func::result_type
operator() ( typename Func::argument_type arg ) {
return ( (*the_func)( arg ) );
}

Func & get ( void ) {
return ( *the_func );
}

Func const & get ( void ) const {
return ( *the_func );
}

};

Similar trickery can be applied to reduce the cost of
copying for large objects, in which case reference countng
becomes an invisible performance hack.

Note that shared_ptr<is actually overkill in this context.
It's support for polymorphism, incomplete types, and a custom
deleter is not needed. A simple intrusive reference counting
smart pointer (not working with incomplete types) fits this
bill neatly.

Example 2 [deep copy pointers]
=========

C++ has value semantics. However, variables are not polymorphic.
You have to use a pointer to support polymorphism. Deep copy
pointers come as close as possible to polymorphic variables
as you can get in C++ (if only we could overload the dod-operator).

A particular example is tr1::function<>, which under the hood
is a deep copy pointer that forwards the function interface to
the pointee.

Example 3 [ownership models]
=========

Smart pointers do not manage resources magically for you, but
sometimes their semantics makes enforcing an ownership model
easier. For instance, a shared resource could be realized like
this:
struct A {};

class SharedResource {

// could be polymorphic
struct Descriptor {

Descriptor ( A a )
{}

void close ( void ) {}

// could be virtual
int some_method ( int ) {
return ( 1 );
}

};

std::tr1::shared_ptr< Descriptor the_ptr;

public:

~SharedResource ( void ) {
assert( ! is_open() );
}

enum mode { ok, busy, error_1, error_2 };

// you can only open a resource if you don't have one
mode open ( A a ) {
if ( ! is_open() ) {
try {
Descriptor * ptr = new Descriptor ( a );
the_ptr.reset( ptr ); // hopefully strongly safe
}
catch( ... ) {
// return whatever is needed
}
return ( ok );
}
return ( busy );
}

// only the last owner can close the resource
bool close ( void ) {
if ( the_ptr.unique() ) {
the_ptr->close(); // may throw
the_ptr.reset();
return ( true );
}
return ( false );
}

// the last owner cannot disown:
bool disown ( void ) {
if ( is_shared() ) {
the_ptr.reset();
return ( true );
}
return ( false );
}

bool is_open ( void ) const {
return ( the_ptr );
}

bool is_shared ( void ) const {
return ( is_open() && ( ! the_ptr.unique() ) );
}
// forward interface
// =================

int some_method ( int arg ) {
assert( is_open() );
the_ptr->some_method( arg );
}

};

Note that the shared_ptr does not show in the interface


On the other hand, there are sometimes reasons to use a
smart pointer directly, although I always feel a little
uneasy. Example:

#include <memory>

class UserCommand {
public:

// ...

virtual
~UserCommand ( void ) {}

};

// magic source of commands.
// in real life, this is polymorphic.
UserCommand * getUserInput ( void ) {
return new UserCommand;
}
class MessageHandler {
public:

// ...

virtual
void operator() ( UserCommand const & cmd,
bool & do_terminate );
// UserCommand is polymorphic

virtual
~MessageHandler ( void ) {}

};
struct MyException {};

void event_loop ( MessageHandler & the_handler ) {
// MessageHandler is polymorphic
try {
bool last_run = false;
do {
// neeed for pointer because of polymorphism:
UserCommand * the_command = getUserInput();
the_handler( *the_command, last_run );
} while ( last_run );
}
catch ( MyException const & e ) {
if ( false ) {
// placeholder for things that can be
// handled here
} else {
throw( e );
}
}
}

The event_loop as written is buggy. If the line

the_handler( *the_command, last_run );

throws, we leak memory. One can use std::auto_ptr<to
rectify things:

void event_loop ( MessageHandler & the_handler ) {
// MessageHandler is polymorphic
try {
bool last_run = false;
do {
// neeed for pointer because of polymorphism:
std::auto_ptr< UserCommand the_command ( getUserInput() );
the_handler ( *the_command, last_run );
} while ( last_run );
}
catch ( MyException const & e ) {
if ( false ) {
// placeholder for things that can be
// handled here
} else {
throw( e );
}
}
}

Best

Kai-Uwe Bu
Jul 21 '07 #32

P: n/a
On Sat, 21 Jul 2007 04:04:25 +0200, Kai-Uwe Bux wrote:
>Pointers in C++ are heavily overloaded. They offer two main
features at once, namely (a) decoupling life-time from scope
and (b) support for polymorphism. If you want the later, you
are inviting upon you the perrils of the former.
Pointers in C++ (and C) have only 2 features: referencing and
de-referencing. Pointers per se have nothing to do with "life-time"
management. OTOH, 'smart pointers' intermingle ultra-lightweight
pointer functionality with heavy, unrelated tasks (like allocating
refernce counters).
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 21 '07 #33

P: n/a
Roland Pibinger wrote:
On Sat, 21 Jul 2007 04:04:25 +0200, Kai-Uwe Bux wrote:
>Pointers in C++ are heavily overloaded. They offer two main
features at once, namely (a) decoupling life-time from scope
and (b) support for polymorphism. If you want the later, you
are inviting upon you the perrils of the former.

Pointers in C++ (and C) have only 2 features: referencing and
de-referencing. Pointers per se have nothing to do with "life-time"
management. OTOH, 'smart pointers' intermingle ultra-lightweight
pointer functionality with heavy, unrelated tasks (like allocating
refernce counters).

So what about RAII ? It's really an important and good C++ technique.
And smart pointers allow you not to take care of memory management,
adding only few additionnal allocations. IMHO, smart pointers are worth
the price, except _maybe_ for real time programs.
Jul 21 '07 #34

P: n/a
Roland Pibinger wrote:
On Sat, 21 Jul 2007 04:04:25 +0200, Kai-Uwe Bux wrote:
>>Pointers in C++ are heavily overloaded. They offer two main
features at once, namely (a) decoupling life-time from scope
and (b) support for polymorphism. If you want the later, you
are inviting upon you the perrils of the former.

Pointers in C++ (and C) have only 2 features: referencing and
de-referencing. Pointers per se have nothing to do with "life-time"
management.
That depends on what you mean by "per se". What I meant is that pointers are
the core language feature that _creates the possibility_ of explicit
life-time management. By writing

T * p = new T ( some args );

I create a T-object whose life-time is independent of the scope in which the
creating statement occurs and whose life-time will rather be ended by the
corresponding delete statement. Which other mechanism for doing explicit
life-time management (not involving pointers) is there in the core
language?
Best

Kai-Uwe Bux

Jul 21 '07 #35

P: n/a
On Fri, 20 Jul 2007 22:17:54 +0200, James Kanze <ja*********@gmail.com>
wrote:
>I had a 3 hours meeting today with some fellow programmers
that are partly not convinced about using smart pointers in
C++.

Does that mean that they are convinced that one should never use
them, or that they are convinced that they aren't a silver
bullet, and should only be used where appropriate (which isn't
really all that often).
They don't want to use them at all. Their argument is that performance is
priority #1 ignoring other goals like stability and maintainability or
resource constraints like project time and budget.
[...]
>I've been explaining the advantages of smart pointers
endlessly (which are currently used in all our C++ software;
we use the Boost smart pointers) as I'm seriously concerned
that there is a shift to raw pointers.

That's interesting. I've always found that trying to use them
systematically (rather than just in specific cases) caused a lot
of extra effort for no gain.
I admit that I've been using them rather systematically. The less time I
have to spend looking around for memory leaks the more time I can
concentrate on other things or the earlier I can finish a project. Given
that the projects I'm involved in typically suffer under heavy resource
constraints I find it a luxury to evaluate the pointer type every time I
need to use a pointer. As I'm also not always happy with the code quality
of the projects I'm responsible for I assume that making everyone use
smart pointers contributes more to the code quality than giving them a
choice (if you don't trust someone to make a correct choice you don't
trust him either to be able to write correct code with raw pointers). Thus
I wonder if the problems smart pointers might cause (like a possible
performance impact) are not actually negligibile compared to the problems
they solve as developers have more time to concentrate on other things
(the ones who write the code and the others who have to test and maintain
the code later).
>We are not developing system software but rather normal
Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but
after that endless discussion I wonder if I'm too strict. Any
serious arguments not to use smart pointers?

Not to use them in the occasional cases where they are
appropriate, none. But that's true for a lot of things.
Absolutely. But I wonder how this should work in practice as in the
projects I've been involved in there are typically more problems to solve
and details to take care of than resources available. And I don't think my
situation is exceptional. Your situation might be different (looking at to
your sig I wonder if you are a consultant :-). That said my experience so
far is that in practice smart pointers are a tool you automatically use
all the time if you aim for high code quality under heavy resource
constraints. As I might have been mislead I asked for opinions in this
newsgroup for a reality check (thanks for all your opinions so far!).

Boris
Jul 21 '07 #36

P: n/a
On Sat, 21 Jul 2007 11:52:05 +0200, Alp Mestan wrote:
>So what about RAII ? It's really an important and good C++ technique.
Yes, but RAII doesn't include the creation of pointer-like classes by
overloading operator* and operator->. RAII means that "allocation and
deallocation disappear from the surface level of your code"
(http://www.artima.com/intv/modern3.html).
>And smart pointers allow you not to take care of memory management,
adding only few additionnal allocations.
The only potential use case for 'smart pointers' is when a pointer to
a dynamically allocated object shall be returned from a function. If
you avoid returning dynamically allocated objects (for design
considerations) the desire for 'smart pointers' vanishes.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 21 '07 #37

P: n/a
On Sat, 21 Jul 2007 12:30:54 +0200, Kai-Uwe Bux wrote:
>What I meant is that pointers are
the core language feature that _creates the possibility_ of explicit
life-time management.
Pointers create the possibility to reference objects (stack-, heap-,
global objects). There is no intrinsic necessity to extend pointers to
object-lifetime managers.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 21 '07 #38

P: n/a

"Roland Pibinger" <rp*****@yahoo.comwrote in message
news:46**************@news.utanet.at...
On Sat, 21 Jul 2007 12:30:54 +0200, Kai-Uwe Bux wrote:
>>What I meant is that pointers are
the core language feature that _creates the possibility_ of explicit
life-time management.

Pointers create the possibility to reference objects (stack-, heap-,
global objects). There is no intrinsic necessity to extend pointers to
object-lifetime managers.
Okay, there seems to be a lot of argument over whether or not pointers are
needed for memory management. But I have not yet heard anyone talk about
HOW one avoids using pointers to manage dynamically allocated memory.
Therefore, I have to ask the (apparently naive) question, if you don't use
pointers for memory management, what do you use? Surely you cannot write
every program without dynamically allocating some memory, and therefore not
ever need to manage that memory?

Is there some (Zen-like?) level of software development that somehow manages
to avoid memory allocation, and therefore the need to deallocate it? What
am I missing here?

- Dennis
Jul 21 '07 #39

P: n/a
Roland Pibinger wrote:
On Sat, 21 Jul 2007 12:30:54 +0200, Kai-Uwe Bux wrote:
>>What I meant is that pointers are
the core language feature that _creates the possibility_ of explicit
life-time management.

Pointers create the possibility to reference objects (stack-, heap-,
global objects).
That too. But they also create the conceptual split of the pointer and the
pointee which is necessary to decouple life-time from scope. Only values
can leave a scope, since all local objects are destroyed. Since a pointer
value can leave the scope, the possibility for pointee-life-time management
arises.

There seems to be a little disagreement about the data type T*. You seem to
claim that for this type the derefencing operation * and the address
operator & are the only primitive operations. I would maintain that new T
and delete() are also primitive operations on objects of type T*.
There is no intrinsic necessity to extend pointers to object-lifetime
managers.
I will concede that you can write a program that uses pointers but does not
contain any new() or delete() statements. I will also grant you that for
those cases, replacing pointers by smart pointers would be pointless (if at
all possible). However, as soon as you have a new() or a delete() statement
in your program, you _are_ managing life-times whether you like it or not.

However, my claim that you quoted is that pointers are necessary to do
explicit life-time management (which is not to say that each and every use
of pointers amounts to life-time management). What other mechanisms for
explicit life-time management do you find in the core language?
Best

Kai-Uwe Bux
Jul 22 '07 #40

P: n/a
On Sun, 22 Jul 2007 02:00:12 +0200, Kai-Uwe Bux wrote:
>However, my claim that you quoted is that pointers are necessary to do
explicit life-time management (which is not to say that each and every use
of pointers amounts to life-time management). What other mechanisms for
explicit life-time management do you find in the core language?
It's beyond question that you need real pointers to access dynamically
created objects, e.g. to manage their lifetime. There's also no doubt
(to me) that destructors in combination with automatic objects, a.k.a.
RAII, are the best thing ever invented in C++. But that doesn't mean
that objects that mimic real pointers but do something 'smart' under
the hood (e.g. lifetime management) are a good idea too.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 22 '07 #41

P: n/a
Roland Pibinger wrote:
On Sun, 22 Jul 2007 02:00:12 +0200, Kai-Uwe Bux wrote:
>>However, my claim that you quoted is that pointers are necessary to do
explicit life-time management (which is not to say that each and every use
of pointers amounts to life-time management). What other mechanisms for
explicit life-time management do you find in the core language?

It's beyond question that you need real pointers to access dynamically
created objects, e.g. to manage their lifetime. There's also no doubt
(to me) that destructors in combination with automatic objects, a.k.a.
RAII, are the best thing ever invented in C++. But that doesn't mean
that objects that mimic real pointers but do something 'smart' under
the hood (e.g. lifetime management) are a good idea too.
Good, we finally reached some common ground: that RAII is good does not mean
that smart pointers are good too. That just is an independent question.

Upthread, I think, I did not make an unqualified general statement that
using smart pointers is a good idea per se. Instead, I observed that they
_can_ play a role in reducing the trickness of programs involving
dynamically allocated objects. However, I am not really interested in
general remarks about smart pointers being smart or dumb because I don't
consider unspecific generalities particularly helpful in making design
decisions; and therefore, I gave specific examples where I found smart
pointer useful / convenient. Maybe a more specific discussion about
particular use cases would be more interesting.
Best

Kai-Uwe Bux
Jul 22 '07 #42

P: n/a


On 22 Jul, 09:08, rpbg...@yahoo.com (Roland Pibinger) wrote:
On Sun, 22 Jul 2007 02:00:12 +0200, Kai-Uwe Bux wrote:
However, my claim that you quoted is that pointers are necessary to do
explicit life-time management (which is not to say that each and every use
of pointers amounts to life-time management). What other mechanisms for
explicit life-time management do you find in the core language?

It's beyond question that you need real pointers to access dynamically
created objects, e.g. to manage their lifetime. There's also no doubt
(to me) that destructors in combination with automatic objects, a.k.a.
RAII, are the best thing ever invented in C++. But that doesn't mean
that objects that mimic real pointers but do something 'smart' under
the hood (e.g. lifetime management) are a good idea too.
IMO this whole debate would be much more interesting with some example
high level specification (allowing for any differences in useage
between smart pointers and raw pointers), and then the anti raw
pointer enthusiasts could implement it using raw pointers and the
pro's could implement it using smart pointers. I have no doubt that if
measured in terms of raw speed the raw pointers would win hands down,
however the other part to this contest, that is admittedly harder to
judge and that would carry twice the weight, is how easy is this
thing to write and maintain?
As a warm up. Here is a somewhat vague spec of one library I found
useful. Anyone that has used a ducktyping language may see something
familiar.

One library I have found surprisingly useful is a C++ directory tree.
The thing was thrown together basically for fun but since writing it I
have found a huge variety of uses.
The tree has one interesting characteristic, which is that you can
throw any type of data into it
The tree is comprised of various types of nodes, each which carries a
unique id in its directory level. So far I have implemented the
following:

abstract_node : The ABC node, but one that can be instantiated. very
politically incorrect but useful for debugging..

leaf_node<T: a terminal node that can holds a 'T'. N.B: where one
tree can hold infinite different and unrelated types of T.

branch_node<Container : A branch that uses Container for its child
elements. So far I have only implemented vector and list, but ideally
it should be able to use a map.

container_with_leaf<Container: I found it useful to have a branch
with some element accessable directly from its id. This type of node
can look like either a branch or a leaf.

The thing is implemented using boost::shared_ptr and weak_ptr and
internally uses a large amount of dynamic casting. Originally getting
a child returned a weak_ptr, but I found this extremely tedious, so I
restricted use of weak_ptr to getting a nodes parent I have thought of
reimplementing it with raw pointers to see what difference it would
make, both in terms of ease of writing the code and in terms of
performance. I suspect that the performance under shared_ptr is
extremely poor, but I also suspect that it would be more difficult to
code and maintain using raw pointers. I emphasise that I don't know
though !

At the end some code where the tree is set up as a parser for some
simplified html source. N.B This is just one specific use. I have also
used it for other things.. (I hope to publish the source for the tree
one day as part of my super-quan distro...)
As part of the above challenge, It is expected that whatever crap you
throw at the dom that you will be informed that you have done
something wrong by some sort of std::exception derived exception...

The two sides can then try to find ways to screw the others versions
up ;-)

example use... (The following only shows a small sample of its
functionality).

anything::ptr is some sort of shared_ptr in my impl. In this setup The
node ids are looked up as encountered directly in the source text.

N.B Not all function ptrs in following have the same sig ;-)

void quanta::html::doc::setup_dom_functions()
{
using quanta::dom::add_branch;
using quanta::dom::list_branch;
using quanta::dom::add_element;

list_branch::ptr html
= add_branch<std::list>(html_root,"html",&parse_html _tag);

list_branch::ptr head
= add_branch<std::list>(html,"head",&parse_head_tag) ;

add_element(head,"text-css",&parse_text_css);
list_branch::ptr body
= add_branch<std::list>(html,"body",&parse_body_tag) ;

add_element(body,"text",&parse_text);
add_element(body,"comment", &parse_comment);

//necessary to look up the correct function for the following cases
typedef void (*pf)( std::istream & ,
quanta::html::body_content_list::ptr ,
quanta::html::tag_identifier::ptr
);

add_element(body,"a",&parse_a_tag);

add_element(body,"p",static_cast<pf>(&parse_list_t ag<quanta::html::p_tag>));

add_element(body,"div",static_cast<pf>(&parse_list _tag<quanta::html::div_tag>));

add_element(body,"pre",static_cast<pf>(&parse_list _tag<quanta::html::pre_tag>));

add_element(body,"span",static_cast<pf>(&parse_lis t_tag<quanta::html::span_tag>));
add_element(body,"h1",static_cast<pf>(&parse_list_ tag<quanta::html::h_tag<1>
>));
add_element(body,"h2",static_cast<pf>(&parse_list_ tag<quanta::html::h_tag<2>
>));
add_element(body,"h3",static_cast<pf>(&parse_list_ tag<quanta::html::h_tag<3>
>));
add_element(body,"h4",static_cast<pf>(&parse_list_ tag<quanta::html::h_tag<4>
>));
add_element(body,"h5",static_cast<pf>(&parse_list_ tag<quanta::html::h_tag<5>
>));
add_element(body,"h6",static_cast<pf>(&parse_list_ tag<quanta::html::h_tag<6>
>));
list_branch::ptr table = add_branch<std::list>(body,"table",
&parse_table_tag);

list_branch::ptr tr =
add_branch<std::list>(table,"tr",&parse_table_tr_t ag);

add_element(tr,"td",&parse_table_tr_td_tag);
}

regards
Andy Little

Jul 22 '07 #43

P: n/a

Boris wrote:
Their main concern is a
possible performance impact. I've been explaining the advantages of smart
pointers endlessly (which are currently used in all our C++ software; we
use the Boost smart pointers) as I'm seriously concerned that there is a
shift to raw pointers.
In our projects we mainly use boost::scoped_ptr for heap-based
members. We often use auto_ptr as constructor parameters which we
then
release for ownership by scoped_ptrs. The performance overhead for
scoped_ptrs are insignificant.

We rarely use shared_ptrs. I'm
not comfortable with the constraints that they have, especially
the constraints that you can't read/write simultaneously when
accessed via multiple threads. Normal pointers don't have that
constraint. We (or I) use shared pointers mostly for objects that
require custom deletion (like file/pipe handles, for instance) or
objects that dictate how they get destroyed. In this case access
to these objects happen through normal pointers anyway, but the
destruction happens via the (only) owner of a shared_ptr.

I've never had the need to use shared_ptr in a container. Getting
around
the copy symantics burden has never been a problem. I'm looking at
giving boost::ptr_container a try, but have not had the need yet.
Regads,

Werner

Jul 23 '07 #44

P: n/a
Boris a écrit :
On Fri, 20 Jul 2007 22:17:54 +0200, James Kanze <ja*********@gmail.com>
wrote:
>>I had a 3 hours meeting today with some fellow programmers
that are partly not convinced about using smart pointers in
C++.

Does that mean that they are convinced that one should never use
them, or that they are convinced that they aren't a silver
bullet, and should only be used where appropriate (which isn't
really all that often).

They don't want to use them at all. Their argument is that performance
is priority #1 ignoring other goals like stability and maintainability
or resource constraints like project time and budget.
That's a concern easy to address. Is performance an issue ? Is there any
benchmark available on the ressources already used ?
>
>[...]
>>I've been explaining the advantages of smart pointers
endlessly (which are currently used in all our C++ software;
we use the Boost smart pointers) as I'm seriously concerned
that there is a shift to raw pointers.

That's interesting. I've always found that trying to use them
systematically (rather than just in specific cases) caused a lot
of extra effort for no gain.

I admit that I've been using them rather systematically. The less time I
have to spend looking around for memory leaks the more time I can
concentrate on other things or the earlier I can finish a project.
I am not sure memory leaks are that common in the main case and usually
easy to find. Problems arise when there are complex object life time.
Given
that the projects I'm involved in typically suffer under heavy resource
constraints I find it a luxury to evaluate the pointer type every time I
need to use a pointer.
As I'm also not always happy with the code quality of the projects
Do you have any defect management report, tool or metric that show so or
is it a purely subjective perception ?
I'm responsible for I assume that making
everyone use smart pointers contributes more to the code quality than
giving them a choice (if you don't trust someone to make a correct
choice you don't trust him either to be able to write correct code with
raw pointers).
Make a programmer use something he is not convinced of is a sure way to
dispirit your team. Showing them you don't trust them to do their job
correctly is a proven bad idea.

An approch that sometimes work (it depends on your relationship) is to
expose the problem (with strong backing/report ...) to them and *ASK*
them what you (you and them as a team) can do. Eventually, they may be
more perceptive about using smart pointers if it is really a good idea
or to find an alternative solution.

Nothing to do with C++ here.

Michael
Jul 23 '07 #45

P: n/a
On Jul 21, 3:08 pm, Boris <bo...@gtemail.netwrote:
On Fri, 20 Jul 2007 22:17:54 +0200, James Kanze <james.ka...@gmail.com>
wrote:
I had a 3 hours meeting today with some fellow programmers
that are partly not convinced about using smart pointers in
C++.
Does that mean that they are convinced that one should never use
them, or that they are convinced that they aren't a silver
bullet, and should only be used where appropriate (which isn't
really all that often).
They don't want to use them at all. Their argument is that
performance is priority #1 ignoring other goals like
stability and maintainability or resource constraints like
project time and budget.
That's just stupid. There may be places where they cause a
performance problem (though IMHO it's unlikely); if so, the
profiler will reveal them, and you can try to work out something
faster. They're not a silver bullet, but they are convenient in
specific cases, and it would be silly to refuse to use them in
such cases, just because they might be slower.

Of course, if the other programmers on the team consider
their speculations about unmeasured performance more important
than project time and budget, it really doesn't matter what you
do. You're screwed from the start.
[...]
I've been explaining the advantages of smart pointers
endlessly (which are currently used in all our C++ software;
we use the Boost smart pointers) as I'm seriously concerned
that there is a shift to raw pointers.
That's interesting. I've always found that trying to use them
systematically (rather than just in specific cases) caused a lot
of extra effort for no gain.
I admit that I've been using them rather systematically. The
less time I have to spend looking around for memory leaks the
more time I can concentrate on other things or the earlier I
can finish a project.
That's why I use the Boehm collector:-). But even without it,
most of the cases involving dynamic memory (at least in my
applications) also involve explicit, application controlled
lifetime. The real problem isn't so much memory leaks, since we
know when to delete the object, but dangling pointers, since
it's easy to forget to notify someone that we are being deleted.

Note that these objects often contain pointers to other such
objects, for navigation, and these pointers often create cycles.
You can't just replace them all with boost::shared_ptr, and
expect to get rid of memory leaks.

That's most of the objects, of course, and without the Boehm
collector, there is a distinct subset of cases where I do use
something like shared_ptr. It doesn't represent the majority of
my objects, but it's not an empty set, either.
Given that the projects I'm involved in typically suffer
under heavy resource constraints I find it a luxury to
evaluate the pointer type every time I need to use a pointer.
Which is what you have to do with smart pointers.
As I'm also not always happy with the code quality of the
projects I'm responsible for I assume that making everyone use
smart pointers contributes more to the code quality than
giving them a choice (if you don't trust someone to make a
correct choice you don't trust him either to be able to write
correct code with raw pointers).
If you don't trust someone to make a correct choice, you don't
trust him to be able to write correct code. The type of
pointers involved don't change anything.
Thus I wonder if the problems smart pointers might cause
(like a possible performance impact) are not actually
negligibile compared to the problems they solve as developers
have more time to concentrate on other things (the ones who
write the code and the others who have to test and maintain
the code later).
I'm not sure I follow. Smart pointers are a low level
implementation technique. They don't free you from having to
consider object lifetime at the design level. When the design
says that a specific smart pointer can do the job, of course,
it's that much less new code you have to write. But my
experience has been that in practice, such cases aren't all that
common (and most of the time, are better handled with garbage
collection, which is even less work).
We are not developing system software but rather normal
Windows programs (with exceptions turned on). I wouldn't want
to write a C++ program without smart pointers any more but
after that endless discussion I wonder if I'm too strict. Any
serious arguments not to use smart pointers?
Not to use them in the occasional cases where they are
appropriate, none. But that's true for a lot of things.
Absolutely. But I wonder how this should work in practice as
in the projects I've been involved in there are typically more
problems to solve and details to take care of than resources
available.
Sure. Any time you can factor out commonality is good, and if
there is a commonality in the lifetime management of certain
classes of objects, it's good if you can factor it out into a
common smart pointer. In practice, however, I find that this
just isn't the case that often.
And I don't think my situation is exceptional.
Your situation might be different (looking at to your sig I
wonder if you are a consultant :-).
I'm not sure what you mean by "consultant". I'm certainly a
consultant in Germany; programmers have to pay an additional
local tax, which consultants are exempt from. But I mostly
write code.
That said my experience so far is that in practice smart
pointers are a tool you automatically use all the time if you
aim for high code quality under heavy resource constraints.
And my experience is that automatically using just about any
tool results in misuse, and poor code quality. Most pointers in
my code are raw pointers, simply because most pointers are used
for navigation, in one way or another. Most "objects" are local
variables, with lifetime automatically handled by the compiler;
the second largest group requires explicit lifetime management
according to application specific requirements, and can't be
automized by some generic smart pointer.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 23 '07 #46

P: n/a
On Mon, 23 Jul 2007 09:49:05 +0200, Michael DOUBEZ
<mi************@free.frwrote:
[...]Make a programmer use something he is not convinced of is a sure
way to dispirit your team. Showing them you don't trust them to do their
job correctly is a proven bad idea.
Letting them go ahead and do whatever they like to do is even worse as you
can shut down the company soon afterwards.
An approch that sometimes work (it depends on your relationship) is to
expose the problem (with strong backing/report ...) to them and *ASK*
them what you (you and them as a team) can do. Eventually, they may be
more perceptive about using smart pointers if it is really a good idea
or to find an alternative solution.
It's months ago that I tried this.

Boris
Jul 23 '07 #47

P: n/a
Boris a écrit :
On Mon, 23 Jul 2007 09:49:05 +0200, Michael DOUBEZ
<mi************@free.frwrote:
>[...]Make a programmer use something he is not convinced of is a sure
way to dispirit your team. Showing them you don't trust them to do
their job correctly is a proven bad idea.

Letting them go ahead and do whatever they like to do is even worse as
you can shut down the company soon afterwards.
Keeping people in a project when they resent it has the same result.
The bear or the wolf: choose who will eat you.
>An approch that sometimes work (it depends on your relationship) is to
expose the problem (with strong backing/report ...) to them and *ASK*
them what you (you and them as a team) can do. Eventually, they may be
more perceptive about using smart pointers if it is really a good idea
or to find an alternative solution.

It's months ago that I tried this.
I didn't say it was a silver bullet. I have had, in the past, this kind
of situation; it is hard work.
I don't think negociation or more technical point will get you anywhere
since you already got a "no".
Have you tried to speak to the leader of the group and ask him to
perform some benchmark (diverting 2 days off the project's budget) ?
If you can sway him and your technical points are valid, you may get the
lever you need.

Michael

NOTE: this is OT here. I tried to answer by mail but your address is
unknown.
Jul 23 '07 #48

P: n/a
On Sun, 22 Jul 2007 02:53:10 -0700, kwikius wrote:
>One library I have found surprisingly useful is a C++ directory tree.
The thing was thrown together basically for fun but since writing it I
have found a huge variety of uses.
The tree has one interesting characteristic, which is that you can
throw any type of data into it
The tree is comprised of various types of nodes, each which carries a
unique id in its directory level.
Seems to be a tree structure (like e.g. a DOM tree). I'd implement it
in such a way that each node creates and ownes its child nodes. When
the root nodes goes out of scope all nodes are deleted in classic RAII
manner. Since ownership is never returned or transferred 'smart
pointers' need not be taken into consideration.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jul 23 '07 #49

P: n/a
On 23 Jul, 18:28, rpbg...@yahoo.com (Roland Pibinger) wrote:
On Sun, 22 Jul 2007 02:53:10 -0700, kwikius wrote:
One library I have found surprisingly useful is a C++ directory tree.
The thing was thrown together basically for fun but since writing it I
have found a huge variety of uses.
The tree has one interesting characteristic, which is that you can
throw any type of data into it
The tree is comprised of various types of nodes, each which carries a
unique id in its directory level.

Seems to be a tree structure (like e.g. a DOM tree). I'd implement it
in such a way that each node creates and ownes its child nodes. When
the root nodes goes out of scope all nodes are deleted in classic RAII
manner. Since ownership is never returned or transferred 'smart
pointers' need not be taken into consideration.
Well, I did a raw pointer port. Its attractive since shared_ptr is my
last dependency on the boost library. The actual number of deletes I
had to write was one, which was in a loop in the container(template)
node dtor.

That only leaves one problem which is the root node. You can either
declare it on the stack or new it on the heap, though then you have to
remember to delete. This does amount to a problem, since exceptions
are quite a frequent occurence, due to say trying to access nodes that
don't exist so you now have to think about management.

Declaring the root on the stack means you have to use a different
syntax , e.g &root rather than root, and it is slightly less flexible
as it is more difficult to modify the code, if say you want to make
the old root a sub node of some new super-root. This is quite possible
e.g in a GUI menu-tree.

I suspect that porting is easier than starting from scratch. IIRC I
did get one assert form the original when trying to access an empty
ptr.

For this application the differences are relatively trivial, but you
can see them starting to mount up in a more complex application and
mistakes happening. IOW I think there is an advantage in the smart
pointer from the viewpoint of simplicity, but for performance and
memory use raw pointers would definitely be far superior, though I
havent benchmarked it.

regards
Andy Little
Jul 24 '07 #50

54 Replies

This discussion thread is closed

Replies have been disabled for this discussion.