Never ever use a raw pointer when a smart pointer can do the same job

Discussion in 'C++' started by Hicham Mouline, Aug 13, 2009.

  1. .... my colleague says.

    I disagree on the "Never".

    Opinions about this "rule of thumb" welcome.

    regards,
    Hicham Mouline, Aug 13, 2009
    #1
    1. Advertising

  2. "Hicham Mouline" <> writes:
    > ... my colleague says.
    > I disagree on the "Never".
    > Opinions about this "rule of thumb" welcome.


    Never use a smart pointer when a garbage collector can do the same job.

    --
    __Pascal Bourguignon__
    Pascal J. Bourguignon, Aug 13, 2009
    #2
    1. Advertising

  3. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    Hicham Mouline wrote:
    > ... my colleague says.
    >
    > I disagree on the "Never".
    >
    > Opinions about this "rule of thumb" welcome.


    What's the definition of "the same job"? They are for different jobs.
    Can a screwdriver do a chisel's job? Could you drive a screw with a
    chisel? What do you do if you don't have a light crowbar, but have a
    strong screwdriver near-by? So, I say, bullsh!t. I use raw pointer
    when I need to use a raw pointer and I use a smart pointer when I need
    to use a smart pointer. If I don't have the facility at hand, I *might*
    spend time implementing it, or I simply use what's available, in the
    best manner possible, to achieve the goal in front of me.

    Also, tell your colleague, the [counter-]saying is "Never say 'never'"
    or "All generalizations are wrong". You may need to explain the word
    "oxymoron" to him/her (without offending them).

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 13, 2009
    #3
  4. Hicham Mouline

    Noah Roberts Guest

    Re: Never ever use a raw pointer when a smart pointer can do thesame job

    Victor Bazarov wrote:
    > Hicham Mouline wrote:
    >> ... my colleague says.
    >>
    >> I disagree on the "Never".
    >>
    >> Opinions about this "rule of thumb" welcome.

    >
    > What's the definition of "the same job"? They are for different jobs.
    > Can a screwdriver do a chisel's job? Could you drive a screw with a
    > chisel? What do you do if you don't have a light crowbar, but have a
    > strong screwdriver near-by? So, I say, bullsh!t. I use raw pointer
    > when I need to use a raw pointer and I use a smart pointer when I need
    > to use a smart pointer.


    What purpose does a raw pointer serve?

    Almost any case when you need a heap allocated data blob can be solved
    by the use of raii objects such as std::vector or wrapping such
    allocations in a smart pointer such as scoped_ptr, shared_ptr, or even
    std::auto_ptr. If any of those object do what you need you should use
    them because NOT using raii leaves you with all the problems raii answers.

    Most times when you want to pass a raw pointer it's because you're
    actually wanting a simple reference to some externally owned data. Most
    of these cases should be resolved by using exactly what you want: a
    reference. The only case when this is not possible is when you are
    creating an object that:

    a) needs an assignment operator that does a shallow copy (or anything
    else where you'd override the reference without assigning to the object
    you're referring to)

    b) can't initialize the reference upon construction.

    c) You're not allowed to ignore warnings and aren't allowed to override
    the "assignment operator could not be created" warning (in which case a
    reference will break the coding standard you're working in)

    Note that not all uses of a pointer are solved by a smart pointer but
    most uses ARE solved by the use of something besides a raw pointer.

    There are exceptions to any standard. I think a standard that says,
    "Wrap every raw pointer in an RAII object," is a good standard that
    allows the team to dictate when to override (not the whim of some
    stubborn developer who thinks they don't need RAII). The standard
    given, "...when a smart pointer can do the same job," seems to maybe be
    even better since it dictates exactly when to use a smart pointer and
    when not to. On the other hand, it seems to leave question of
    definition about when a smart pointer can do the same job.

    I'd be willing to entertain arguments to the contrary but the project
    I'm managing uses such a standard and I've yet to see a convincing
    argument that it's a bad one. We have our exceptions when we need them
    (such as working with WX) but generally wrap any pointer creation into
    some sort of smart object that will delete it at the right time.
    Noah Roberts, Aug 13, 2009
    #4
  5. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    Noah Roberts wrote:
    > Victor Bazarov wrote:
    >> Hicham Mouline wrote:
    >>> ... my colleague says.
    >>>
    >>> I disagree on the "Never".
    >>>
    >>> Opinions about this "rule of thumb" welcome.

    >>
    >> What's the definition of "the same job"? They are for different jobs.
    >> Can a screwdriver do a chisel's job? Could you drive a screw with a
    >> chisel? What do you do if you don't have a light crowbar, but have a
    >> strong screwdriver near-by? So, I say, bullsh!t. I use raw pointer
    >> when I need to use a raw pointer and I use a smart pointer when I need
    >> to use a smart pointer.

    >
    > What purpose does a raw pointer serve?
    >
    > Almost any case when you need a heap allocated data blob [..]


    You answered your own question - it's not a heap allocated data blob (to
    start, anyway).

    > Most times when you want to pass a raw pointer it's because you're
    > actually wanting a simple reference to some externally owned data. Most
    > of these cases should be resolved by using exactly what you want: a
    > reference. The only case when this is not possible is when you are
    > creating an object that:
    >
    > a) needs an assignment operator that does a shallow copy (or anything
    > else where you'd override the reference without assigning to the object
    > you're referring to)
    >
    > b) can't initialize the reference upon construction.
    >
    > c) You're not allowed to ignore warnings and aren't allowed to override
    > the "assignment operator could not be created" warning (in which case a
    > reference will break the coding standard you're working in)


    or d) the referred object is actually allowed to be *missing*. How'd
    you do that with a reference?

    A smart pointer is nothing but a wrapper around a raw pointer. There is
    no escape, you *have to* use a raw pointer somewhere, even if you're the
    one who implements that wrapper (or the smart pointer).

    > Note that not all uses of a pointer are solved by a smart pointer but
    > most uses ARE solved by the use of something besides a raw pointer.


    "Most", "most", "most"... The key word. There goes the "never"...

    > There are exceptions to any standard. I think a standard that says,
    > "Wrap every raw pointer in an RAII object," is a good standard that
    > allows the team to dictate when to override (not the whim of some
    > stubborn developer who thinks they don't need RAII). The standard
    > given, "...when a smart pointer can do the same job," seems to maybe be
    > even better since it dictates exactly when to use a smart pointer and
    > when not to. On the other hand, it seems to leave question of
    > definition about when a smart pointer can do the same job.
    >
    > I'd be willing to entertain arguments to the contrary but the project
    > I'm managing uses such a standard and I've yet to see a convincing
    > argument that it's a bad one. We have our exceptions when we need them
    > (such as working with WX) but generally wrap any pointer creation into
    > some sort of smart object that will delete it at the right time.


    Delete what? An automatic object? A static object? A function? With
    a raw pointer I have a choice what to pass to the function that can
    expect "something or nothing", and that something can be basically
    anything, not just a dynamically allocated blob. And don't tell me all
    your objects exist on the heap. Mine don't.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 13, 2009
    #5
  6. "Noah Roberts" <> wrote in message
    news:4a844571$0$7453$...
    > Victor Bazarov wrote:
    >> Hicham Mouline wrote:
    >>> ... my colleague says.
    >>>
    >>> I disagree on the "Never".
    >>>
    >>> Opinions about this "rule of thumb" welcome.

    >>
    >> What's the definition of "the same job"? They are for different jobs.
    >> Can a screwdriver do a chisel's job? Could you drive a screw with a
    >> chisel? What do you do if you don't have a light crowbar, but have a
    >> strong screwdriver near-by? So, I say, bullsh!t. I use raw pointer when
    >> I need to use a raw pointer and I use a smart pointer when I need to use
    >> a smart pointer.

    >
    > What purpose does a raw pointer serve?
    >


    when doing custom memory management;
    when working with data which is "not an object" (loosely structured or
    unstructured regions of memory, ...);
    ....

    basically, not all tasks involve "objects", sometimes the task may involve
    something with far less "identity" or "structure"...

    AKA: raw pointers, for raw memory...


    raw memory has not gone away, just as ASM has not gone away.
    some tasks are best solved with raw memory, just as some tasks are best
    solved with ASM (namely, those which if attempted to be done in C or C++
    would tend to become some horrible monstrosity, or be essentially impossible
    in the first place, and yes, some such cases exist...).


    it is much like a typical car contains a spare tire and a cross-wrench...
    will you typically need these while driving?...
    probably not.

    but should the minority case happen, and one has a flat or a blow-out, then
    suddenly the need for such things will present itself...

    likewise goes for code.
    BGB / cr88192, Aug 13, 2009
    #6
  7. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    Noah Roberts wrote:
    > What purpose does a raw pointer serve?


    The same as (random access) iterators?
    Juha Nieminen, Aug 13, 2009
    #7
  8. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    On Thu, 13 Aug 2009 11:39:22 -0400, Victor Bazarov wrote:

    > Hicham Mouline wrote:
    >> ... my colleague says.
    >>
    >> I disagree on the "Never".
    >>
    >> Opinions about this "rule of thumb" welcome.

    >
    > What's the definition of "the same job"? They are for different jobs.
    > Can a screwdriver do a chisel's job? Could you drive a screw with a
    > chisel? What do you do if you don't have a light crowbar, but have a
    > strong screwdriver near-by? So, I say, bullsh!t. I use raw pointer
    > when I need to use a raw pointer and I use a smart pointer when I need
    > to use a smart pointer. If I don't have the facility at hand, I *might*
    > spend time implementing it, or I simply use what's available, in the
    > best manner possible, to achieve the goal in front of me.
    >
    > Also, tell your colleague, the [counter-]saying is "Never say 'never'"
    > or "All generalizations are wrong". You may need to explain the word
    > "oxymoron" to him/her (without offending them).
    >
    > V


    Actually, you can use a chisel as a screwdriver, you just have to hit
    very hard. Like as in, really hard.
    D. Frankinson, Aug 14, 2009
    #8
  9. Hicham Mouline

    James Kanze Guest

    Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On Aug 13, 5:15 pm, "Hicham Mouline" <> wrote:
    > ... my colleague says.


    > I disagree on the "Never".


    > Opinions about this "rule of thumb" welcome.


    It's one of the stupidest rules I've heard of. The rule should
    be just the opposite: "never use a smart pointer when a raw
    pointer will do the job". But even that's stupid, in a
    way---smart pointers and raw pointers are different beasts, and
    generally not interchangeable. Generally, if a smart pointer
    will do the job, a raw pointer can't, and vice versa (unless you
    have some very stupid and useless smart pointers).

    In practice, in most application level software (at least in the
    domains I've worked in), most pointers will be raw, because a
    smart pointer would not do the job---at least not correctly.
    But most is not all, and there will almost always be some cases
    where the smart pointer is more appropriate as well.

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 14, 2009
    #9
  10. Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On 13 Aug, 17:55, Noah Roberts <> wrote:
    > Victor Bazarov wrote:
    > > Hicham Mouline wrote:


    > >> ["Never ever use a raw pointer when a smart pointer can do the same
    > >> job"] my colleague says.

    >
    > >> I disagree on the "Never".

    >
    > >> Opinions about this "rule of thumb" welcome.

    >
    > > What's the definition of "the same job"?  They are for different jobs..
    > > [...] I use raw pointer when I need to use a raw pointer and I use a
    > > smart pointer when I need to use a smart pointer.

    >
    > What purpose does a raw pointer serve?


    to point to things...

    > Almost any case when you need a heap allocated data blob can be solved
    > by the use of raii objects such as std::vector [etc.]


    >  If any of those object do what you need you should use
    > them because NOT using raii leaves you with all the problems raii answers..


    but RAII is not the only reson to use pointers.

    polymorphism and threaded data structures


    > Most times


    but not *all* times

    > when you want to pass a raw pointer it's because you're
    > actually wanting a simple reference to some externally owned data.  Most
    > of these cases should be resolved by using exactly what you want: a
    > reference.  The only case when this is not possible is when you are
    > creating an object that:


    <snip>

    > There are exceptions to any standard.


    not in my universe

    > I think a standard that says,
    > "Wrap every raw pointer in an RAII object," is a good standard that
    > allows the team to dictate when to override


    so why not say "Wrap every raw pointer in an RAII object, except where
    explicitly overridden by the Design Authority"

    I think our trouble is I think absolutes are absolute and
    you don't.

    I don't think "never" is morally equivalent to "hardly ever"

    "but that's the worse thing that could possibly happen,
    but its worse than that!"
    engineer on seeing a system log

    <snip>

    --
    Nick Keighley
    Nick Keighley, Aug 14, 2009
    #10
  11. Hicham Mouline

    James Kanze Guest

    Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On Aug 13, 5:18 pm, (Pascal J. Bourguignon)
    wrote:
    > "Hicham Mouline" <> writes:
    > > ... my colleague says.
    > > I disagree on the "Never".
    > > Opinions about this "rule of thumb" welcome.


    > Never use a smart pointer when a garbage collector can do the
    > same job.


    :)

    I agree, but most pointers aren't implicated in any way in
    memory management, so neither garbage collection nor smart
    pointer is relevant. (That's not totally true, of course---even
    in such cases, garbage collection can make the code more
    robust.)

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 14, 2009
    #11
  12. Hicham Mouline

    James Kanze Guest

    Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On Aug 13, 6:55 pm, Noah Roberts <> wrote:
    > Victor Bazarov wrote:
    > > Hicham Mouline wrote:
    > >> ... my colleague says.


    > >> I disagree on the "Never".


    > >> Opinions about this "rule of thumb" welcome.


    > > What's the definition of "the same job"? They are for
    > > different jobs. Can a screwdriver do a chisel's job? Could
    > > you drive a screw with a chisel? What do you do if you
    > > don't have a light crowbar, but have a strong screwdriver
    > > near-by? So, I say, bullsh!t. I use raw pointer when I
    > > need to use a raw pointer and I use a smart pointer when I
    > > need to use a smart pointer.


    > What purpose does a raw pointer serve?


    Navigation.

    > Almost any case when you need a heap allocated data blob can
    > be solved by the use of raii objects such as std::vector or
    > wrapping such allocations in a smart pointer such as
    > scoped_ptr, shared_ptr, or even std::auto_ptr.


    That's not the case in any of the applications I've worked on.
    At the application level, lifetime is generally very
    deterministic; objects are created and deleted as a result of
    specific input from external sources. Using a scoped_ptr,
    shared_ptr or an auto_ptr on any of these will result in a
    double delete. (It's sometimes useful to use an auto_ptr during
    the actual construction, until the transaction has completed, or
    the object has been registered wherever it has to be
    registered.)

    Conceivably, there would be a use for a smart pointer which
    works the opposite of garbage collection---deleting the object
    causes the pointer to be null'ed. My site (when it was
    accessible) had a ManagedPtr for that. In practice, however,
    this is really only useful for 1->{0,1} relationships, and not
    always for those (the object containing the pointer often has to
    react to the fact that the pointed to object has disappeared); I
    don't think I've used this smart pointer more than once or twice
    in the more than ten years since I implemented it.

    > If any of those object do what you need you should use them
    > because NOT using raii leaves you with all the problems raii
    > answers.


    RAII isn't really very appropriate for managing the lifetime of
    dynamically allocated object, since RAII depends on lifetime
    corresponding to a scope, and if the lifetime of an object
    corresponds to a scope, then you don't allocate it dynamically.

    In certain cases, shared_ptr can serve as a poor man's garbage
    collector, but it's very error prone (compared to a real garbage
    collector).

    > Most times when you want to pass a raw pointer it's because
    > you're actually wanting a simple reference to some externally
    > owned data. Most of these cases should be resolved by using
    > exactly what you want: a reference.


    Unless it's an optional argument, where you might want to pass
    a null pointer. But I agree with you in general---when passing
    arguments, prefer references to pointers when possible. Most
    pointers end up in the objects, themselves---class member
    variables---where they are used for navigation. And must be
    reseated, so references are out. A lot of the relationships
    expressed by pointers are 1->n, which means some sort of
    container of pointers---std::vector< T* >, std::set< T* >,
    std::map< IdType, T* >, etc.

    > The only case when this is not possible is when you are
    > creating an object that:


    > a) needs an assignment operator that does a shallow copy (or
    > anything else where you'd override the reference without
    > assigning to the object you're referring to)


    > b) can't initialize the reference upon construction.


    Or have to reseat it.

    > c) You're not allowed to ignore warnings and aren't allowed to
    > override the "assignment operator could not be created"
    > warning (in which case a reference will break the coding
    > standard you're working in)


    > Note that not all uses of a pointer are solved by a smart
    > pointer but most uses ARE solved by the use of something
    > besides a raw pointer.


    > There are exceptions to any standard. I think a standard that
    > says, "Wrap every raw pointer in an RAII object," is a good
    > standard that allows the team to dictate when to override (not
    > the whim of some stubborn developer who thinks they don't need
    > RAII). The standard given, "...when a smart pointer can do
    > the same job," seems to maybe be even better since it dictates
    > exactly when to use a smart pointer and when not to. On the
    > other hand, it seems to leave question of definition about
    > when a smart pointer can do the same job.


    > I'd be willing to entertain arguments to the contrary but the
    > project I'm managing uses such a standard and I've yet to see
    > a convincing argument that it's a bad one. We have our
    > exceptions when we need them (such as working with WX) but
    > generally wrap any pointer creation into some sort of smart
    > object that will delete it at the right time.


    I'm curious as to the type of software you work on. You
    obviously have some experience, but in all of the application
    software I've seen (low level libraries are a different case),
    dynamically allocated objects which have lifetimes corresponding
    to those of a local variable are extremely rare---almost all
    have lifetimes which begin and end in response to an external
    stimulus. And almost all pointers are used for navigation, and
    only navigation.

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 14, 2009
    #12
  13. Hicham Mouline

    James Kanze Guest

    Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On Aug 13, 11:54 pm, Juha Nieminen <> wrote:
    > Noah Roberts wrote:
    > > What purpose does a raw pointer serve?


    > The same as (random access) iterators?


    Ah, but those are smart pointers:). Not the type Noah was
    thinking of, I think, but they're certainly more like smart
    pointers than they are iterators. (In normal usage, "random
    access iterator" is an oxymoron.)

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 14, 2009
    #13
  14. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    * James Kanze:
    > On Aug 13, 5:15 pm, "Hicham Mouline" <> wrote:
    >> ... my colleague says.

    >
    >> I disagree on the "Never".

    >
    >> Opinions about this "rule of thumb" welcome.

    >
    > It's one of the stupidest rules I've heard of. The rule should
    > be just the opposite: "never use a smart pointer when a raw
    > pointer will do the job".


    Here the reader will, IMHO, benefit from considering the context:

    * James is one of the few who uses garbage collection in C++.
    A typical programmer isn't.

    * James is very much aware of where raw pointers "will do the
    job", with a sophisticated understanding of what "the job" is.
    A typical programmer isn't.

    * James typically works with well-designed classes.
    A typical programmer relates to classes that aren't that well
    designed.

    So although James' rule fits James, IMHO it doesn't fit the typical programmer.

    For the typical programmer the main problem is to get the programmer to apply
    automated and secure lifetime management, at all (smart pointers also solve
    other problems, such as automated checking of availability, automated mutually
    exclusive access, and so on, but such concerns are lesser issues).


    > But even that's stupid, in a
    > way---smart pointers and raw pointers are different beasts, and
    > generally not interchangeable. Generally, if a smart pointer
    > will do the job, a raw pointer can't, and vice versa (unless you
    > have some very stupid and useless smart pointers).


    That statement relies on a sophisticated understanding of what "do the job" entails.

    For a more simple understanding, such as "can be made to (apparently) work",
    it's not the case that raw pointers can't do the job of smart pointers.

    This follows from simple logic: at any point where a smart pointer would do
    something extra, such as updating a reference count, that extra action, or
    something equivalent and possibly more efficient, can be done explicitly with a
    raw pointer.

    Using a raw pointer where a smart pointer would be appropriate is the same as
    basic "if" and "goto" being sufficient to express "for", "while", "do", "else"
    and conditional operator. It's not impossible. When one considers only an
    individual statement or two the "goto" based code is even simpler, because there
    are only very simple "if" choices and very simple direct jumps, that's all (of
    course at a higher level of abstraction the spaghetti code isn't simple).

    And in the same way as with "goto", with a very narrow focus on individual
    statements using a raw pointer might seem simpler, because there are only very
    simple operations. And in the same way as with "goto", at a higher level of
    abstraction, considering what the code accomplishes, the raw pointer based code
    isn't simple. For in the same way as "goto", what the raw pointer lacks is (1)
    restrictions on what you can do, and (2) automation of various actions.


    > In practice, in most application level software (at least in the
    > domains I've worked in), most pointers will be raw, because a
    > smart pointer would not do the job---at least not correctly.
    > But most is not all, and there will almost always be some cases
    > where the smart pointer is more appropriate as well.


    "most application level software" is IMHO a severe over-generalization.


    Cheers,

    - Alf
    Alf P. Steinbach, Aug 14, 2009
    #14
  15. Hicham Mouline

    James Kanze Guest

    Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On Aug 14, 12:07 pm, Nick Keighley <>
    wrote:
    > On 13 Aug, 17:55, Noah Roberts <> wrote:


    [...]
    > > There are exceptions to any standard.


    > not in my universe


    The very first rule in any coding guidelines should always be
    that any rule in the guidelines can be violated, provided the
    programmer can justify the violation.

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 14, 2009
    #15
  16. Hicham Mouline

    James Kanze Guest

    Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On Aug 14, 12:50 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:


    > > On Aug 13, 5:15 pm, "Hicham Mouline" <> wrote:
    > >> ... my colleague says.


    > >> I disagree on the "Never".


    > >> Opinions about this "rule of thumb" welcome.


    > > It's one of the stupidest rules I've heard of. The rule should
    > > be just the opposite: "never use a smart pointer when a raw
    > > pointer will do the job".


    > Here the reader will, IMHO, benefit from considering the context:


    > * James is one of the few who uses garbage collection in C++.
    > A typical programmer isn't.


    I don't always use garbage collection, for many reasons.

    > * James is very much aware of where raw pointers "will do the
    > job", with a sophisticated understanding of what "the job" is.
    > A typical programmer isn't.


    A programmer who doesn't know what a raw pointer is, and what it
    should be used for, simply isn't competent in C++.

    > * James typically works with well-designed classes.
    > A typical programmer relates to classes that aren't that well
    > designed.


    > So although James' rule fits James, IMHO it doesn't fit the
    > typical programmer.


    Sorry, it's a rule I (and all of my collegues) use everywhere.

    As I pointed out in the remainder of my posting, raw pointers
    and smart pointers don't really overlap; there are very few
    cases where both will do the job.

    > For the typical programmer the main problem is to get the
    > programmer to apply automated and secure lifetime management,


    For the typical programmer, the main problem is to get him to
    understand that fundamental design issues, like lifetime, must
    be decided at the design level. And the problem is not to
    manage lifetime with pointers (since that doesn't work), but to
    make pointer use coincide with lifetime (which generally
    involves some variant of the observer pattern).

    > at all (smart pointers also solve other problems, such as
    > automated checking of availability, automated mutually
    > exclusive access, and so on, but such concerns are lesser
    > issues).


    I've used smart pointers for transaction management, in one
    somewhat special case, and I use them from time to time to
    manage mutually exclusive access (e.g. to a singleton). I use
    std::auto_ptr rather religiously for communication between
    threads---you can't access through the pointer once you've
    passed it to the other thread. I've also used smart pointers
    (my own invasive reference counted pointer) for memory
    management in cases where garbage collection wasn't available,
    but using smart pointers for this is extremely error prone, and
    requires a good deal of precaution. There are lot's of cases
    where smart pointers are appropriate, but except for the last,
    they have nothing to do with memory management issues, and never
    with object lifetime issues.

    > > But even that's stupid, in a way---smart pointers and raw
    > > pointers are different beasts, and generally not
    > > interchangeable. Generally, if a smart pointer will do the
    > > job, a raw pointer can't, and vice versa (unless you have
    > > some very stupid and useless smart pointers).


    > That statement relies on a sophisticated understanding of what
    > "do the job" entails.


    If you don't know what the job is, you have a problem. A
    serious problem, which can't be masked over by any simple
    programming technique, like smart pointers.

    > For a more simple understanding, such as "can be made to
    > (apparently) work", it's not the case that raw pointers can't
    > do the job of smart pointers.


    > This follows from simple logic: at any point where a smart
    > pointer would do something extra, such as updating a reference
    > count, that extra action, or something equivalent and possibly
    > more efficient, can be done explicitly with a raw pointer.


    Not reasonably. Strictly speaking, not at all; you need extra
    code. But of course, you're just playing word games.

    [...]
    > > In practice, in most application level software (at least in
    > > the domains I've worked in), most pointers will be raw,
    > > because a smart pointer would not do the job---at least not
    > > correctly. But most is not all, and there will almost
    > > always be some cases where the smart pointer is more
    > > appropriate as well.


    > "most application level software" is IMHO a severe
    > over-generalization.


    Yes and no. Show me a case of application level software where
    a smart pointer is the most appropriate solution, and we can
    discuss whether it is frequent enough to exclude the "most" in
    my statement. (I very definitely know of a few cases where
    smart pointers are appropriate, but they aren't common enough to
    invalidate the "most".)

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 14, 2009
    #16
  17. Re: Never ever use a raw pointer when a smart pointer can do the samejob

    On 14 Aug, 11:25, James Kanze <> wrote:
    > On Aug 13, 6:55 pm, Noah Roberts <> wrote:
    > > Victor Bazarov wrote:
    > > > Hicham Mouline wrote:


    > > >> ... my colleague says


    "Never ever use a raw pointer when a smart pointer can do the
    same job"

    <snip>

    > > > [...] I use raw pointer when I
    > > > need to use a raw pointer and I use a smart pointer when I
    > > > need to use a smart pointer.

    >
    > > What purpose does a raw pointer serve?

    >
    > Navigation.
    >
    > > Almost any case when you need a heap allocated data blob can
    > > be solved by the use of raii objects such as std::vector or
    > > wrapping such allocations in a smart pointer such as
    > > scoped_ptr, shared_ptr, or even std::auto_ptr.

    >
    > That's not the case in any of the applications I've worked on.
    > At the application level, lifetime is generally very
    > deterministic; objects are created and deleted as a result of
    > specific input from external sources.  Using a scoped_ptr,
    > shared_ptr or an auto_ptr on any of these will result in a
    > double delete.  (It's sometimes useful to use an auto_ptr during
    > the actual construction, until the transaction has completed, or
    > the object has been registered wherever it has to be
    > registered.)


    what about sub-objects or resources? The high level object
    may have a deterministic lifetime but the stuff it accumlates
    during its lifetime has to be destroyed at the same time.
    Is that a justification for a smart pointer or should you just
    write your destructors correctly?

    <snip>

    > > If any of those object do what you need you should use them
    > > because NOT using raii leaves you with all the problems raii
    > > answers.

    >
    > RAII isn't really very appropriate for managing the lifetime of
    > dynamically allocated object, since RAII depends on lifetime
    > corresponding to a scope, and if the lifetime of an object
    > corresponds to a scope, then you don't allocate it dynamically.


    yes! I'd noticed that. Calls in a communications system don't
    vanish at the end of a block!

    <snip>

    > > Most times when you want to pass a raw pointer it's because
    > > you're actually wanting a simple reference to some externally
    > > owned data.  Most of these cases should be resolved by using
    > > exactly what you want: a reference.

    >
    > Unless it's an optional argument, where you might want to pass
    > a null pointer.  But I agree with you in general---when passing
    > arguments, prefer references to pointers when possible.  Most
    > pointers end up in the objects, themselves---class member
    > variables---where they are used for navigation.  And must be
    > reseated, so references are out.  A lot of the relationships
    > expressed by pointers are 1->n, which means some sort of
    > container of pointers---std::vector< T* >, std::set< T* >,
    > std::map< IdType, T* >, etc.


    yes. I was beginning to think I worked in some very odd domains!

    <snip>

    > > c) You're not allowed to ignore warnings and aren't allowed to
    > > override the "assignment operator could not be created"
    > > warning (in which case a reference will break the coding
    > > standard you're working in)
    > > Note that not all uses of a pointer are solved by a smart
    > > pointer but most uses ARE solved by the use of something
    > > besides a raw pointer.
    > > There are exceptions to any standard.  I think a standard that
    > > says, "Wrap every raw pointer in an RAII object," is a good
    > > standard that allows the team to dictate when to override (not
    > > the whim of some stubborn developer who thinks they don't need
    > > RAII).  The standard given, "...when a smart pointer can do
    > > the same job," seems to maybe be even better since it dictates
    > > exactly when to use a smart pointer and when not to.  On the
    > > other hand, it seems to leave question of definition about
    > > when a smart pointer can do the same job.
    > > I'd be willing to entertain arguments to the contrary but the
    > > project I'm managing uses such a standard and I've yet to see
    > > a convincing argument that it's a bad one.  We have our
    > > exceptions when we need them (such as working with WX) but
    > > generally wrap any pointer creation into some sort of smart
    > > object that will delete it at the right time.

    >
    > I'm curious as to the type of software you work on.  You
    > obviously have some experience, but in all of the application
    > software I've seen (low level libraries are a different case),
    > dynamically allocated objects which have lifetimes corresponding
    > to those of a local variable are extremely rare---almost all
    > have lifetimes which begin and end in response to an external
    > stimulus.  And almost all pointers are used for navigation, and
    > only navigation.


    my applications are pseudo-embedded; they very much respond to
    events that are not determined by the scope structure of the
    program.
    Nick Keighley, Aug 14, 2009
    #17
  18. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    * James Kanze:
    >
    > Conceivably, there would be a use for a smart pointer which
    > works the opposite of garbage collection---deleting the object
    > causes the pointer to be null'ed. My site (when it was
    > accessible) had a ManagedPtr for that. In practice, however,
    > this is really only useful for 1->{0,1} relationships, and not
    > always for those (the object containing the pointer often has to
    > react to the fact that the pointed to object has disappeared); I
    > don't think I've used this smart pointer more than once or twice
    > in the more than ten years since I implemented it.


    It would be nice if objects that may encounter "unrecoverable failures" were
    only accessible via such smart pointers.

    The smart pointer would do all the validity checking, e.g. instead as with
    current iostreams where every iostream operation checks the state and possibly
    chooses to do nothing, the smart pointer would centralize the checking and throw
    an exception.

    It's an old idea. I once, many years ago, communicated with DDJ about writing an
    article about this, but nothing more came of it than a tentative first attempt.
    I don't know exactly why: the policy of DDJ seems to be to cut communication
    when they're not interested (I think there was a fundamental change in DDJ when
    they took up former Object Magazine, a wishy-washy buzzword publication, and
    I'm not even sure that DDJ is still published in hard-copy, I haven't seen it
    for ages). Anyway, those who are interested can find implementations on the net.
    E.g. I posted a very limited implementation in this group just a few days ago.

    But whereas I once saw GUI widgets (which are generally self-destroying) as a
    main usage for such a pointer, I now hold the view that they're better accessed
    simply via raw pointers. For the cases where a checking smart pointer would
    detect access after destruction, are very few. In the majority of cases, for a
    GUI widget the checking smart pointer would just be added complication.

    However, files and socket objects and such, I think that's the proper usage. For
    in contrast to GUI widgets these kinds of objects suffer from having natural
    zombie states, states where nearly all operations are invalid. A checking smart
    pointer can then centralize and enforce the validity (non-zombie) checking.


    Cheers,

    - Alf
    Alf P. Steinbach, Aug 14, 2009
    #18
  19. >"James Kanze" <> wrote in message
    >news:cb0f1497-14d8-4b15-b3b6->...
    >On Aug 13, 5:15 pm, "Hicham Mouline" <> wrote:
    >> ... my colleague says.


    >> I disagree on the "Never".


    >> Opinions about this "rule of thumb" welcome.


    >It's one of the stupidest rules I've heard of. The rule should
    >be just the opposite: "never use a smart pointer when a raw
    >pointer will do the job". But even that's stupid, in a
    >way---smart pointers and raw pointers are different beasts, and
    >generally not interchangeable. Generally, if a smart pointer
    >will do the job, a raw pointer can't, and vice versa (unless you
    >have some very stupid and useless smart pointers).


    >In practice, in most application level software (at least in the
    >domains I've worked in), most pointers will be raw, because a
    >smart pointer would not do the job---at least not correctly.
    >But most is not all, and there will almost always be some cases
    >where the smart pointer is more appropriate as well.


    It is interesting to see so many different opinions about this.
    Perhaps, the discussion can be fine tuned if I put down the use case
    (trivial one) here:

    We have a 3rd party application that accepts to load shared dynamic
    libraries, this is on windows.
    The application requires a number of entry points into the DLL. These are
    "exported" functions, 2 of these
    are

    // with C linkage convention (ie , they use C and not C++)
    int initialize(some_type* f);
    void finalize();

    1 translation unit where we implement this requirement looks like



    extern "C" {

    static const our_adapter* adapter=0; // global static raw pointer

    int initialize(const some_type* f)
    {
    if (f==0)
    {
    return failure; /// 3rd application will ignore this dll
    }
    adapter = new our_adapter(*f); /// ctor never fails. If new fails, the
    3rd party application crashes (we decided it's ok)
    }

    //// we axiomatize that initialize() is called once before finalize() and
    that the 3rd party application calls these just once
    void finalize()
    {
    delete adapter;
    }

    // other required function
    int other_function()
    {
    adapter->do_something();
    }

    }


    I would have had as a global variable the our_adapter itself, but its ctor
    requires the "f", so I used a pointer instead.
    Because of the exisiting symmetry between initalize and finalize, new'ing
    and deleting seem to me appropriate.

    My colleague insists I should use auto_ptr<our_adapter> instead of a raw
    pointer here, and then said as a general rule,
    never use a raw pointer when the smart pointer will work, hence the post.

    could I have opinions about this particular case?

    regards,
    Hicham Mouline, Aug 14, 2009
    #19
  20. Re: Never ever use a raw pointer when a smart pointer can do thesame job

    * James Kanze:
    >
    > For the typical programmer, the main problem is to get him to
    > understand that fundamental design issues, like lifetime, must
    > be decided at the design level. And the problem is not to
    > manage lifetime with [smart] pointers (since that doesn't work), but to
    > make pointer use coincide with lifetime (which generally
    > involves some variant of the observer pattern).


    One might argue the same about using, e.g. "for" loops: it doesn't work as a
    magic solution to the problem of designing loops.

    The inference that therefore "goto" should be preferred, is, however, absurd.


    Cheers,

    - Alf
    Alf P. Steinbach, Aug 14, 2009
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Soren Kuula
    Replies:
    1
    Views:
    440
    Henry S. Thompson
    Dec 1, 2005
  2. Kevin
    Replies:
    4
    Views:
    412
    Irrwahn Grausewitz
    Oct 17, 2003
  3. coala
    Replies:
    3
    Views:
    364
    coala
    Sep 6, 2006
  4. coala
    Replies:
    1
    Views:
    579
    Victor Bazarov
    Sep 6, 2006
  5. Jason
    Replies:
    0
    Views:
    187
    Jason
    Jul 6, 2004
Loading...

Share This Page