|
Boost : |
Subject: Re: [boost] [smart_ptr] Interest in the missing smart pointer (that can target the stack)
From: Noah (duneroadrunner_at_[hidden])
Date: 2016-01-30 13:31:09
On 1/29/2016 7:00 PM, Rob Stewart wrote:
>
> Have a look at boost::intrusive_ptr.
If I understand boost::intrusive_ptr correctly, and I'm not totally sure
that I do, I think it kind of further makes the case for including
registered_ptrs. This post
http://baptiste-wicht.com/posts/2011/11/boost-intrusive_ptr.html implies
the point of boost::intrusive_ptr is increased performance. But it
appears that, like shared_ptr, it's meant to be used for heap
allocations. But of course, often the biggest performance improvement by
far would come from avoiding any heap allocation whatsoever. Which is
what (at least one implementation of) registered_ptr can do no problem.
Some simple benchmarks here
http://duneroadrunner.github.io/SaferCPlusPlus/#simple-benchmarks show
that registered_ptrs targeting the stack far outperform even native
pointers targeting the heap (when you include the allocation and
deallocations). I'm thinking that maybe registered_ptr could be
re-branded the "high performance" smart pointer. In which case, one
could pose the question as "does it's warts (it's issues with primitive
types and 'final' classes) justify excluding the 'high performance'
smart pointer"?
> Many times I don't want to initialize a variable because the branches in the subsequent code select the value. Do your wrappers provide a constructor that permits leaving the value uninitialized?
So first let me say that I'm not proposing a total ban on primitive
types. When you need the performance, and primitive types give you the
performance, use them. But that should be small fraction of the world's
total C++ code. What is antiquated, in my opinion, is that primitive
types are the still the default. In terms of not wanting to initialize
due to subsequent conditional assignment, I would say don't
underestimate the compiler optimizer. When the optimizer can figure out
that the default initialization is redundant, it will remove it for you,
right?
I should note though, that I found it difficult (or impossible) to fully
mimic all the implicit conversion rules of primitive types, so there are
going to be some cases where the substitute classes can't be used
(without rewriting some of your code) for compatibility reasons.
>> And they also address the bug
>> prone implicit conversion between signed and unsigned ints.
>
> Once you do that, shouldn't you go the rest of the way and check all conversions? For example, what about overflow during marketing narrowing?
I don't know what "marketing narrowing" is, but recently on this
newsgroup people have been discussing a "safe integer" or "safe
numerics" library that seems to have taken it all the way, and maybe
even a bit further. My types do check ranges when converting to
different integer/char types. It's been a while, but if anyone's
interested they're implemented here
https://github.com/duneroadrunner/SaferCPlusPlus/blob/master/mseprimitives.h
and examples of their functionality in action are here
https://github.com/duneroadrunner/SaferCPlusPlus/blob/master/msetl_example.cpp
(search for "mse::CInt"). I am not trying to push my specific primitive
substitutes. I'm sure people will (or have) come up with better ones. I
chose certain safety-performance-compatibilty-time-effort tradeoffs when
implementing my primitive substitutes, but I would certainly defer to
anyone else who wants to address the issue. I would say two things though:
One - It might be helpful if boost, or whoever, adopted a standard set
of primitive substitutes that compilers could recognize and optimize for.
And two - By default, an unsigned integer minus another unsigned integer
should really return a signed integer, like my primitives do.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk