When should I use raw pointers over smart pointers?












52














After reading this answer, it looks like it is a best practice to use smart pointers as much as possible, and to reduce the usage of "normal"/raw pointers to minimum.



Is that true?










share|improve this question




















  • 18




    Just for the record, many smart pointer types are just as fast as raw pointers. It's just that when you say "smart pointer", nearly everyone hears it as "shared pointer", and shared pointers are much slower than raw pointers. But scoped_ptr or unique_ptr have no performance overhead. So "I want performance" isn't really a valid excuse for avoiding smart pointers. Just for avoiding shared_ptr specifcially
    – jalf
    Jul 13 '11 at 9:40
















52














After reading this answer, it looks like it is a best practice to use smart pointers as much as possible, and to reduce the usage of "normal"/raw pointers to minimum.



Is that true?










share|improve this question




















  • 18




    Just for the record, many smart pointer types are just as fast as raw pointers. It's just that when you say "smart pointer", nearly everyone hears it as "shared pointer", and shared pointers are much slower than raw pointers. But scoped_ptr or unique_ptr have no performance overhead. So "I want performance" isn't really a valid excuse for avoiding smart pointers. Just for avoiding shared_ptr specifcially
    – jalf
    Jul 13 '11 at 9:40














52












52








52


27





After reading this answer, it looks like it is a best practice to use smart pointers as much as possible, and to reduce the usage of "normal"/raw pointers to minimum.



Is that true?










share|improve this question















After reading this answer, it looks like it is a best practice to use smart pointers as much as possible, and to reduce the usage of "normal"/raw pointers to minimum.



Is that true?







c++ pointers boost smart-pointers






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 23 '17 at 12:34









Community

11




11










asked Jul 13 '11 at 7:44









Alon Gubkin

26.5k49165270




26.5k49165270








  • 18




    Just for the record, many smart pointer types are just as fast as raw pointers. It's just that when you say "smart pointer", nearly everyone hears it as "shared pointer", and shared pointers are much slower than raw pointers. But scoped_ptr or unique_ptr have no performance overhead. So "I want performance" isn't really a valid excuse for avoiding smart pointers. Just for avoiding shared_ptr specifcially
    – jalf
    Jul 13 '11 at 9:40














  • 18




    Just for the record, many smart pointer types are just as fast as raw pointers. It's just that when you say "smart pointer", nearly everyone hears it as "shared pointer", and shared pointers are much slower than raw pointers. But scoped_ptr or unique_ptr have no performance overhead. So "I want performance" isn't really a valid excuse for avoiding smart pointers. Just for avoiding shared_ptr specifcially
    – jalf
    Jul 13 '11 at 9:40








18




18




Just for the record, many smart pointer types are just as fast as raw pointers. It's just that when you say "smart pointer", nearly everyone hears it as "shared pointer", and shared pointers are much slower than raw pointers. But scoped_ptr or unique_ptr have no performance overhead. So "I want performance" isn't really a valid excuse for avoiding smart pointers. Just for avoiding shared_ptr specifcially
– jalf
Jul 13 '11 at 9:40




Just for the record, many smart pointer types are just as fast as raw pointers. It's just that when you say "smart pointer", nearly everyone hears it as "shared pointer", and shared pointers are much slower than raw pointers. But scoped_ptr or unique_ptr have no performance overhead. So "I want performance" isn't really a valid excuse for avoiding smart pointers. Just for avoiding shared_ptr specifcially
– jalf
Jul 13 '11 at 9:40












7 Answers
7






active

oldest

votes


















72














No, it's not true. If a function needs a pointer and has nothing to do with ownership, then I strongly believe that a regular pointer should be passed for the following reasons:




  • No ownership, therefore you don't know what kind of a smart pointer to pass

  • If you pass a specific pointer, like shared_ptr, then you won't be able to pass, say, scoped_ptr


The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.



Example1:



void PrintObject(shared_ptr<const Object> po) //bad
{
if(po)
po->Print();
else
log_error();
}

void PrintObject(const Object* po) //good
{
if(po)
po->Print();
else
log_error();
}


Example2:



Object* createObject() //bad
{
return new Object;
}

some_smart_ptr<Object> createObject() //good
{
return some_smart_ptr<Object>(new Object);
}





share|improve this answer



















  • 13




    An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
    – DanS
    Jul 13 '11 at 7:57






  • 15




    I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
    – Nicol Bolas
    Jul 13 '11 at 7:58






  • 3




    @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
    – DanS
    Jul 13 '11 at 8:09






  • 2




    @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
    – Armen Tsirunyan
    Jul 13 '11 at 8:44






  • 2




    I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
    – user729124
    Jul 13 '11 at 8:52



















14














Using smart pointers to manage ownership is the right thing to do.
Conversely, using raw pointers wherever ownership is not an issue is not wrong.



Here are some perfectly legitimate use of raw pointers (remember, it is always assumed they are non-owning):



where they compete with references




  • argument passing; but references can't be null, so are preferable

  • as class members to denote association rather than composition; usually preferable to references because the semantics of assignment are more straightforward and in addition an invariant set up by the constructors can ensure that they are not 0 for the lifetime of the object

  • as a handle to a (possibly polymorphic) object owned somewhere else; references can't be null so again they are preferable


  • std::bind uses a convention where arguments that are passed are copied into the resulting functor; however std::bind(&T::some_member, this, ...) only makes a copy of the pointer whereas std::bind(&T::some_member, *this, ...) copies the object; std::bind(&T::some_member, std::ref(*this), ...) is an alternative


where they do not compete with references




  • as iterators!

  • argument passing of optional parameters; here they compete with boost::optional<T&>

  • as a handle to a (possibly polymorphic) object owned somewhere else, when they can't be declared at the site of initialization; again, competing with boost::optional<T&>


As a reminder, it's almost always wrong to write a function (that is not a constructor, or a function member that e.g. takes ownership) that accepts a smart pointer unless it in turn pass it to a constructor (e.g. it's correct for std::async because semantically it's close to being a call to the std::thread constructor). If it's synchronous, no need for the smart pointer.





To recap, here's a snippet that demonstrates several of the above uses. We're writing and using a class that applies a functor to every element of an std::vector<int> while writing some output.



class apply_and_log {
public:
// C++03 exception: it's acceptable to pass by pointer to const
// to avoid apply_and_log(std::cout, std::vector<int>())
// notice that our pointer would be left dangling after call to constructor
// this still adds a requirement on the caller that v != 0 or that we throw on 0
apply_and_log(std::ostream& os, std::vector<int> const* v)
: log(&os)
, data(v)
{}

// C++0x alternative
// also usable for C++03 with requirement on v
apply_and_log(std::ostream& os, std::vector<int> const& v)
: log(&os)
, data(&v)
{}
// now apply_and_log(std::cout, std::vector<int> {}) is invalid in C++0x
// && is also acceptable instead of const&&
apply_and_log(std::ostream& os, std::vector<int> const&&) = delete;

// Notice that without effort copy (also move), assignment and destruction
// are correct.
// Class invariants: member pointers are never 0.
// Requirements on construction: the passed stream and vector must outlive *this

typedef std::function<void(std::vector<int> const&)> callback_type;

// optional callback
// alternative: boost::optional<callback_type&>
void
do_work(callback_type* callback)
{
// for convenience
auto& v = *data;

// using raw pointers as iterators
int* begin = &v[0];
int* end = begin + v.size();
// ...

if(callback) {
callback(v);
}
}

private:
// association: we use a pointer
// notice that the type is polymorphic and non-copyable,
// so composition is not a reasonable option
std::ostream* log;

// association: we use a pointer to const
// contrived example for the constructors
std::vector<int> const* data;
};





share|improve this answer































    6














    The use of smart pointers is always recommended because they clearly document the ownership.



    What we really miss, however, is a "blank" smart pointer, one that does not imply any notion of ownership.



    template <typename T>
    class ptr // thanks to Martinho for the name suggestion :)
    {
    public:
    ptr(T* p): _p(p) {}
    template <typename U> ptr(U* p): _p(p) {}
    template <typename SP> ptr(SP const& sp): _p(sp.get()) {}

    T& operator*() const { assert(_p); return *_p; }
    T* operator->() const { assert(_p); return _p; }

    private:
    T* _p;
    }; // class ptr<T>


    This is, indeed, the simplest version of any smart pointer that may exist: a type that documents that it does not own the resource it points too.






    share|improve this answer



















    • 7




      I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
      – user729124
      Jul 13 '11 at 8:49








    • 5




      @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
      – Matthieu M.
      Jul 13 '11 at 8:54






    • 1




      Oh I see. Interesting technique, I'd never have thought of using a class in that way.
      – user729124
      Jul 13 '11 at 8:59






    • 1




      Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
      – R. Martinho Fernandes
      Jul 13 '11 at 9:29






    • 9




      Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
      – jalf
      Jul 13 '11 at 9:48



















    3














    One instance where reference counting (used by shared_ptr in particular) will break down is when you create a cycle out of the pointers (e.g. A points to B, B points to A, or A->B->C->A, or etc). In that case, none of the objects will ever be automatically freed, because they are all keeping each other's reference counts greater than zero.



    For that reason, whenever I am creating objects that have a parent-child relationship (e.g. a tree of objects), I will use shared_ptrs in the parent objects to hold their child objects, but if the child objects need a pointer back to their parent, I will use a plain C/C++ pointer for that.






    share|improve this answer

















    • 6




      Good point, but still that's what weak pointers are for, like boost::weak_ptr
      – Armen Tsirunyan
      Jul 13 '11 at 7:56










    • Ah yes, I'd forgotten about weak_ptr.
      – Jeremy Friesner
      Jul 13 '11 at 8:09



















    1














    Few cases, where you may want to use pointers:




    • Function pointers (obviously no smart pointer)

    • Defining your own smart pointer or container

    • Dealing with low level programming, where raw pointers are crucial

    • Decaying from raw arrays






    share|improve this answer





















    • Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
      – Sebastian Mach
      Jul 13 '11 at 8:02










    • There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
      – Jeremiah Willcock
      Apr 10 '12 at 21:54



















    1














    I think a little bit more thorough answer was given here: Which kind of pointer do I use when?



    Excerpted from that link: "Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope." (bold preserved from the original)



    The problem is that if you're writing code for general use it's not always easy to be absolutely certain the object will outlive the raw pointer. Consider this example:



    struct employee_t {
    employee_t(const std::string& first_name, const std::string& last_name) : m_first_name(first_name), m_last_name(last_name) {}
    std::string m_first_name;
    std::string m_last_name;
    };

    void replace_current_employees_with(const employee_t* p_new_employee, std::list<employee_t>& employee_list) {
    employee_list.clear();
    employee_list.push_back(*p_new_employee);
    }

    void main(int argc, char* argv) {
    std::list<employee_t> current_employee_list;
    current_employee_list.push_back(employee_t("John", "Smith"));
    current_employee_list.push_back(employee_t("Julie", "Jones"));
    employee_t* p_person_who_convinces_boss_to_rehire_him = &(current_employee_list.front());

    replace_current_employees_with(p_person_who_convinces_boss_to_rehire_him, current_employee_list);
    }


    Much to its surprise, the replace_current_employees_with() function can inadvertently cause one of its parameters to be deallocated before it's finished using it.



    So even though it might at first seem like the replace_current_employees_with() function doesn't need ownership of it's parameters, it needs some kind of defense against the possiblity of its parameters being insidiously deallocated before it's finished using them. The simplest solution is to actually take (temporary shared) ownership of the parameter(s), presumably through a shared_ptr.



    But if you really don't want to take ownership, there is now a safe option - and this is the shameless plug portion of the answer - "registered pointers". "registered pointers" are smart pointers that behave like raw pointers, except that they are (automatically) set to null_ptr when the target object is destroyed, and by default, will throw an exception if you try to access an object that has already been deleted.



    Also note that registered pointers can be "disabled" (automatically replaced with their raw pointer counterpart) with a compile-time directive, allowing them to be used (and incur overhead) in debug/test/beta modes only. So you should really have to resort actual raw pointers quite rarely.






    share|improve this answer































      -2














      It is true. I can not see the benefits of raw pointers over smart pointers, especially in a complex project.



      For tempory and lightweight usage, raw pointers are fine though.






      share|improve this answer





















        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6675651%2fwhen-should-i-use-raw-pointers-over-smart-pointers%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        7 Answers
        7






        active

        oldest

        votes








        7 Answers
        7






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        72














        No, it's not true. If a function needs a pointer and has nothing to do with ownership, then I strongly believe that a regular pointer should be passed for the following reasons:




        • No ownership, therefore you don't know what kind of a smart pointer to pass

        • If you pass a specific pointer, like shared_ptr, then you won't be able to pass, say, scoped_ptr


        The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.



        Example1:



        void PrintObject(shared_ptr<const Object> po) //bad
        {
        if(po)
        po->Print();
        else
        log_error();
        }

        void PrintObject(const Object* po) //good
        {
        if(po)
        po->Print();
        else
        log_error();
        }


        Example2:



        Object* createObject() //bad
        {
        return new Object;
        }

        some_smart_ptr<Object> createObject() //good
        {
        return some_smart_ptr<Object>(new Object);
        }





        share|improve this answer



















        • 13




          An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
          – DanS
          Jul 13 '11 at 7:57






        • 15




          I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
          – Nicol Bolas
          Jul 13 '11 at 7:58






        • 3




          @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
          – DanS
          Jul 13 '11 at 8:09






        • 2




          @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
          – Armen Tsirunyan
          Jul 13 '11 at 8:44






        • 2




          I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
          – user729124
          Jul 13 '11 at 8:52
















        72














        No, it's not true. If a function needs a pointer and has nothing to do with ownership, then I strongly believe that a regular pointer should be passed for the following reasons:




        • No ownership, therefore you don't know what kind of a smart pointer to pass

        • If you pass a specific pointer, like shared_ptr, then you won't be able to pass, say, scoped_ptr


        The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.



        Example1:



        void PrintObject(shared_ptr<const Object> po) //bad
        {
        if(po)
        po->Print();
        else
        log_error();
        }

        void PrintObject(const Object* po) //good
        {
        if(po)
        po->Print();
        else
        log_error();
        }


        Example2:



        Object* createObject() //bad
        {
        return new Object;
        }

        some_smart_ptr<Object> createObject() //good
        {
        return some_smart_ptr<Object>(new Object);
        }





        share|improve this answer



















        • 13




          An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
          – DanS
          Jul 13 '11 at 7:57






        • 15




          I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
          – Nicol Bolas
          Jul 13 '11 at 7:58






        • 3




          @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
          – DanS
          Jul 13 '11 at 8:09






        • 2




          @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
          – Armen Tsirunyan
          Jul 13 '11 at 8:44






        • 2




          I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
          – user729124
          Jul 13 '11 at 8:52














        72












        72








        72






        No, it's not true. If a function needs a pointer and has nothing to do with ownership, then I strongly believe that a regular pointer should be passed for the following reasons:




        • No ownership, therefore you don't know what kind of a smart pointer to pass

        • If you pass a specific pointer, like shared_ptr, then you won't be able to pass, say, scoped_ptr


        The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.



        Example1:



        void PrintObject(shared_ptr<const Object> po) //bad
        {
        if(po)
        po->Print();
        else
        log_error();
        }

        void PrintObject(const Object* po) //good
        {
        if(po)
        po->Print();
        else
        log_error();
        }


        Example2:



        Object* createObject() //bad
        {
        return new Object;
        }

        some_smart_ptr<Object> createObject() //good
        {
        return some_smart_ptr<Object>(new Object);
        }





        share|improve this answer














        No, it's not true. If a function needs a pointer and has nothing to do with ownership, then I strongly believe that a regular pointer should be passed for the following reasons:




        • No ownership, therefore you don't know what kind of a smart pointer to pass

        • If you pass a specific pointer, like shared_ptr, then you won't be able to pass, say, scoped_ptr


        The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.



        Example1:



        void PrintObject(shared_ptr<const Object> po) //bad
        {
        if(po)
        po->Print();
        else
        log_error();
        }

        void PrintObject(const Object* po) //good
        {
        if(po)
        po->Print();
        else
        log_error();
        }


        Example2:



        Object* createObject() //bad
        {
        return new Object;
        }

        some_smart_ptr<Object> createObject() //good
        {
        return some_smart_ptr<Object>(new Object);
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jul 13 '11 at 8:00

























        answered Jul 13 '11 at 7:46









        Armen Tsirunyan

        92.4k43274388




        92.4k43274388








        • 13




          An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
          – DanS
          Jul 13 '11 at 7:57






        • 15




          I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
          – Nicol Bolas
          Jul 13 '11 at 7:58






        • 3




          @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
          – DanS
          Jul 13 '11 at 8:09






        • 2




          @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
          – Armen Tsirunyan
          Jul 13 '11 at 8:44






        • 2




          I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
          – user729124
          Jul 13 '11 at 8:52














        • 13




          An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
          – DanS
          Jul 13 '11 at 7:57






        • 15




          I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
          – Nicol Bolas
          Jul 13 '11 at 7:58






        • 3




          @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
          – DanS
          Jul 13 '11 at 8:09






        • 2




          @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
          – Armen Tsirunyan
          Jul 13 '11 at 8:44






        • 2




          I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
          – user729124
          Jul 13 '11 at 8:52








        13




        13




        An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
        – DanS
        Jul 13 '11 at 7:57




        An alternative in Example1 is to pass a reference as no ownership is transferred - as in the old auto_ptr.
        – DanS
        Jul 13 '11 at 7:57




        15




        15




        I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
        – Nicol Bolas
        Jul 13 '11 at 7:58




        I love the note about ownership (which is what smart pointers are all about). However, you may want to consider that PrintObject should take a const& instead of a const*. That way, you're guaranteed not to be able to transfer ownership, so there's no question of whether PrintObject should take possession of it or not.
        – Nicol Bolas
        Jul 13 '11 at 7:58




        3




        3




        @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
        – DanS
        Jul 13 '11 at 8:09




        @Armen: Yes, but to avoid transfer of ownership you pass a reference. It made sense to me when I wrote it but on reflection is less than clear.
        – DanS
        Jul 13 '11 at 8:09




        2




        2




        @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
        – Armen Tsirunyan
        Jul 13 '11 at 8:44




        @AudioDroid: I don't like top level consts on my function parameters. Even if the pointer did change to point to another address the original pointer passed would remain unaltered
        – Armen Tsirunyan
        Jul 13 '11 at 8:44




        2




        2




        I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
        – user729124
        Jul 13 '11 at 8:52




        I agree that the parameter should be passed by reference if at all possible. I would suggest a raw pointer only be used if the function must not assume ownership and the object is optional so the pointer may need to be NULL.
        – user729124
        Jul 13 '11 at 8:52













        14














        Using smart pointers to manage ownership is the right thing to do.
        Conversely, using raw pointers wherever ownership is not an issue is not wrong.



        Here are some perfectly legitimate use of raw pointers (remember, it is always assumed they are non-owning):



        where they compete with references




        • argument passing; but references can't be null, so are preferable

        • as class members to denote association rather than composition; usually preferable to references because the semantics of assignment are more straightforward and in addition an invariant set up by the constructors can ensure that they are not 0 for the lifetime of the object

        • as a handle to a (possibly polymorphic) object owned somewhere else; references can't be null so again they are preferable


        • std::bind uses a convention where arguments that are passed are copied into the resulting functor; however std::bind(&T::some_member, this, ...) only makes a copy of the pointer whereas std::bind(&T::some_member, *this, ...) copies the object; std::bind(&T::some_member, std::ref(*this), ...) is an alternative


        where they do not compete with references




        • as iterators!

        • argument passing of optional parameters; here they compete with boost::optional<T&>

        • as a handle to a (possibly polymorphic) object owned somewhere else, when they can't be declared at the site of initialization; again, competing with boost::optional<T&>


        As a reminder, it's almost always wrong to write a function (that is not a constructor, or a function member that e.g. takes ownership) that accepts a smart pointer unless it in turn pass it to a constructor (e.g. it's correct for std::async because semantically it's close to being a call to the std::thread constructor). If it's synchronous, no need for the smart pointer.





        To recap, here's a snippet that demonstrates several of the above uses. We're writing and using a class that applies a functor to every element of an std::vector<int> while writing some output.



        class apply_and_log {
        public:
        // C++03 exception: it's acceptable to pass by pointer to const
        // to avoid apply_and_log(std::cout, std::vector<int>())
        // notice that our pointer would be left dangling after call to constructor
        // this still adds a requirement on the caller that v != 0 or that we throw on 0
        apply_and_log(std::ostream& os, std::vector<int> const* v)
        : log(&os)
        , data(v)
        {}

        // C++0x alternative
        // also usable for C++03 with requirement on v
        apply_and_log(std::ostream& os, std::vector<int> const& v)
        : log(&os)
        , data(&v)
        {}
        // now apply_and_log(std::cout, std::vector<int> {}) is invalid in C++0x
        // && is also acceptable instead of const&&
        apply_and_log(std::ostream& os, std::vector<int> const&&) = delete;

        // Notice that without effort copy (also move), assignment and destruction
        // are correct.
        // Class invariants: member pointers are never 0.
        // Requirements on construction: the passed stream and vector must outlive *this

        typedef std::function<void(std::vector<int> const&)> callback_type;

        // optional callback
        // alternative: boost::optional<callback_type&>
        void
        do_work(callback_type* callback)
        {
        // for convenience
        auto& v = *data;

        // using raw pointers as iterators
        int* begin = &v[0];
        int* end = begin + v.size();
        // ...

        if(callback) {
        callback(v);
        }
        }

        private:
        // association: we use a pointer
        // notice that the type is polymorphic and non-copyable,
        // so composition is not a reasonable option
        std::ostream* log;

        // association: we use a pointer to const
        // contrived example for the constructors
        std::vector<int> const* data;
        };





        share|improve this answer




























          14














          Using smart pointers to manage ownership is the right thing to do.
          Conversely, using raw pointers wherever ownership is not an issue is not wrong.



          Here are some perfectly legitimate use of raw pointers (remember, it is always assumed they are non-owning):



          where they compete with references




          • argument passing; but references can't be null, so are preferable

          • as class members to denote association rather than composition; usually preferable to references because the semantics of assignment are more straightforward and in addition an invariant set up by the constructors can ensure that they are not 0 for the lifetime of the object

          • as a handle to a (possibly polymorphic) object owned somewhere else; references can't be null so again they are preferable


          • std::bind uses a convention where arguments that are passed are copied into the resulting functor; however std::bind(&T::some_member, this, ...) only makes a copy of the pointer whereas std::bind(&T::some_member, *this, ...) copies the object; std::bind(&T::some_member, std::ref(*this), ...) is an alternative


          where they do not compete with references




          • as iterators!

          • argument passing of optional parameters; here they compete with boost::optional<T&>

          • as a handle to a (possibly polymorphic) object owned somewhere else, when they can't be declared at the site of initialization; again, competing with boost::optional<T&>


          As a reminder, it's almost always wrong to write a function (that is not a constructor, or a function member that e.g. takes ownership) that accepts a smart pointer unless it in turn pass it to a constructor (e.g. it's correct for std::async because semantically it's close to being a call to the std::thread constructor). If it's synchronous, no need for the smart pointer.





          To recap, here's a snippet that demonstrates several of the above uses. We're writing and using a class that applies a functor to every element of an std::vector<int> while writing some output.



          class apply_and_log {
          public:
          // C++03 exception: it's acceptable to pass by pointer to const
          // to avoid apply_and_log(std::cout, std::vector<int>())
          // notice that our pointer would be left dangling after call to constructor
          // this still adds a requirement on the caller that v != 0 or that we throw on 0
          apply_and_log(std::ostream& os, std::vector<int> const* v)
          : log(&os)
          , data(v)
          {}

          // C++0x alternative
          // also usable for C++03 with requirement on v
          apply_and_log(std::ostream& os, std::vector<int> const& v)
          : log(&os)
          , data(&v)
          {}
          // now apply_and_log(std::cout, std::vector<int> {}) is invalid in C++0x
          // && is also acceptable instead of const&&
          apply_and_log(std::ostream& os, std::vector<int> const&&) = delete;

          // Notice that without effort copy (also move), assignment and destruction
          // are correct.
          // Class invariants: member pointers are never 0.
          // Requirements on construction: the passed stream and vector must outlive *this

          typedef std::function<void(std::vector<int> const&)> callback_type;

          // optional callback
          // alternative: boost::optional<callback_type&>
          void
          do_work(callback_type* callback)
          {
          // for convenience
          auto& v = *data;

          // using raw pointers as iterators
          int* begin = &v[0];
          int* end = begin + v.size();
          // ...

          if(callback) {
          callback(v);
          }
          }

          private:
          // association: we use a pointer
          // notice that the type is polymorphic and non-copyable,
          // so composition is not a reasonable option
          std::ostream* log;

          // association: we use a pointer to const
          // contrived example for the constructors
          std::vector<int> const* data;
          };





          share|improve this answer


























            14












            14








            14






            Using smart pointers to manage ownership is the right thing to do.
            Conversely, using raw pointers wherever ownership is not an issue is not wrong.



            Here are some perfectly legitimate use of raw pointers (remember, it is always assumed they are non-owning):



            where they compete with references




            • argument passing; but references can't be null, so are preferable

            • as class members to denote association rather than composition; usually preferable to references because the semantics of assignment are more straightforward and in addition an invariant set up by the constructors can ensure that they are not 0 for the lifetime of the object

            • as a handle to a (possibly polymorphic) object owned somewhere else; references can't be null so again they are preferable


            • std::bind uses a convention where arguments that are passed are copied into the resulting functor; however std::bind(&T::some_member, this, ...) only makes a copy of the pointer whereas std::bind(&T::some_member, *this, ...) copies the object; std::bind(&T::some_member, std::ref(*this), ...) is an alternative


            where they do not compete with references




            • as iterators!

            • argument passing of optional parameters; here they compete with boost::optional<T&>

            • as a handle to a (possibly polymorphic) object owned somewhere else, when they can't be declared at the site of initialization; again, competing with boost::optional<T&>


            As a reminder, it's almost always wrong to write a function (that is not a constructor, or a function member that e.g. takes ownership) that accepts a smart pointer unless it in turn pass it to a constructor (e.g. it's correct for std::async because semantically it's close to being a call to the std::thread constructor). If it's synchronous, no need for the smart pointer.





            To recap, here's a snippet that demonstrates several of the above uses. We're writing and using a class that applies a functor to every element of an std::vector<int> while writing some output.



            class apply_and_log {
            public:
            // C++03 exception: it's acceptable to pass by pointer to const
            // to avoid apply_and_log(std::cout, std::vector<int>())
            // notice that our pointer would be left dangling after call to constructor
            // this still adds a requirement on the caller that v != 0 or that we throw on 0
            apply_and_log(std::ostream& os, std::vector<int> const* v)
            : log(&os)
            , data(v)
            {}

            // C++0x alternative
            // also usable for C++03 with requirement on v
            apply_and_log(std::ostream& os, std::vector<int> const& v)
            : log(&os)
            , data(&v)
            {}
            // now apply_and_log(std::cout, std::vector<int> {}) is invalid in C++0x
            // && is also acceptable instead of const&&
            apply_and_log(std::ostream& os, std::vector<int> const&&) = delete;

            // Notice that without effort copy (also move), assignment and destruction
            // are correct.
            // Class invariants: member pointers are never 0.
            // Requirements on construction: the passed stream and vector must outlive *this

            typedef std::function<void(std::vector<int> const&)> callback_type;

            // optional callback
            // alternative: boost::optional<callback_type&>
            void
            do_work(callback_type* callback)
            {
            // for convenience
            auto& v = *data;

            // using raw pointers as iterators
            int* begin = &v[0];
            int* end = begin + v.size();
            // ...

            if(callback) {
            callback(v);
            }
            }

            private:
            // association: we use a pointer
            // notice that the type is polymorphic and non-copyable,
            // so composition is not a reasonable option
            std::ostream* log;

            // association: we use a pointer to const
            // contrived example for the constructors
            std::vector<int> const* data;
            };





            share|improve this answer














            Using smart pointers to manage ownership is the right thing to do.
            Conversely, using raw pointers wherever ownership is not an issue is not wrong.



            Here are some perfectly legitimate use of raw pointers (remember, it is always assumed they are non-owning):



            where they compete with references




            • argument passing; but references can't be null, so are preferable

            • as class members to denote association rather than composition; usually preferable to references because the semantics of assignment are more straightforward and in addition an invariant set up by the constructors can ensure that they are not 0 for the lifetime of the object

            • as a handle to a (possibly polymorphic) object owned somewhere else; references can't be null so again they are preferable


            • std::bind uses a convention where arguments that are passed are copied into the resulting functor; however std::bind(&T::some_member, this, ...) only makes a copy of the pointer whereas std::bind(&T::some_member, *this, ...) copies the object; std::bind(&T::some_member, std::ref(*this), ...) is an alternative


            where they do not compete with references




            • as iterators!

            • argument passing of optional parameters; here they compete with boost::optional<T&>

            • as a handle to a (possibly polymorphic) object owned somewhere else, when they can't be declared at the site of initialization; again, competing with boost::optional<T&>


            As a reminder, it's almost always wrong to write a function (that is not a constructor, or a function member that e.g. takes ownership) that accepts a smart pointer unless it in turn pass it to a constructor (e.g. it's correct for std::async because semantically it's close to being a call to the std::thread constructor). If it's synchronous, no need for the smart pointer.





            To recap, here's a snippet that demonstrates several of the above uses. We're writing and using a class that applies a functor to every element of an std::vector<int> while writing some output.



            class apply_and_log {
            public:
            // C++03 exception: it's acceptable to pass by pointer to const
            // to avoid apply_and_log(std::cout, std::vector<int>())
            // notice that our pointer would be left dangling after call to constructor
            // this still adds a requirement on the caller that v != 0 or that we throw on 0
            apply_and_log(std::ostream& os, std::vector<int> const* v)
            : log(&os)
            , data(v)
            {}

            // C++0x alternative
            // also usable for C++03 with requirement on v
            apply_and_log(std::ostream& os, std::vector<int> const& v)
            : log(&os)
            , data(&v)
            {}
            // now apply_and_log(std::cout, std::vector<int> {}) is invalid in C++0x
            // && is also acceptable instead of const&&
            apply_and_log(std::ostream& os, std::vector<int> const&&) = delete;

            // Notice that without effort copy (also move), assignment and destruction
            // are correct.
            // Class invariants: member pointers are never 0.
            // Requirements on construction: the passed stream and vector must outlive *this

            typedef std::function<void(std::vector<int> const&)> callback_type;

            // optional callback
            // alternative: boost::optional<callback_type&>
            void
            do_work(callback_type* callback)
            {
            // for convenience
            auto& v = *data;

            // using raw pointers as iterators
            int* begin = &v[0];
            int* end = begin + v.size();
            // ...

            if(callback) {
            callback(v);
            }
            }

            private:
            // association: we use a pointer
            // notice that the type is polymorphic and non-copyable,
            // so composition is not a reasonable option
            std::ostream* log;

            // association: we use a pointer to const
            // contrived example for the constructors
            std::vector<int> const* data;
            };






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 12 '14 at 13:03









            Igor R.

            10.6k12959




            10.6k12959










            answered Jul 13 '11 at 8:33









            Luc Danton

            30.3k554105




            30.3k554105























                6














                The use of smart pointers is always recommended because they clearly document the ownership.



                What we really miss, however, is a "blank" smart pointer, one that does not imply any notion of ownership.



                template <typename T>
                class ptr // thanks to Martinho for the name suggestion :)
                {
                public:
                ptr(T* p): _p(p) {}
                template <typename U> ptr(U* p): _p(p) {}
                template <typename SP> ptr(SP const& sp): _p(sp.get()) {}

                T& operator*() const { assert(_p); return *_p; }
                T* operator->() const { assert(_p); return _p; }

                private:
                T* _p;
                }; // class ptr<T>


                This is, indeed, the simplest version of any smart pointer that may exist: a type that documents that it does not own the resource it points too.






                share|improve this answer



















                • 7




                  I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
                  – user729124
                  Jul 13 '11 at 8:49








                • 5




                  @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
                  – Matthieu M.
                  Jul 13 '11 at 8:54






                • 1




                  Oh I see. Interesting technique, I'd never have thought of using a class in that way.
                  – user729124
                  Jul 13 '11 at 8:59






                • 1




                  Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
                  – R. Martinho Fernandes
                  Jul 13 '11 at 9:29






                • 9




                  Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
                  – jalf
                  Jul 13 '11 at 9:48
















                6














                The use of smart pointers is always recommended because they clearly document the ownership.



                What we really miss, however, is a "blank" smart pointer, one that does not imply any notion of ownership.



                template <typename T>
                class ptr // thanks to Martinho for the name suggestion :)
                {
                public:
                ptr(T* p): _p(p) {}
                template <typename U> ptr(U* p): _p(p) {}
                template <typename SP> ptr(SP const& sp): _p(sp.get()) {}

                T& operator*() const { assert(_p); return *_p; }
                T* operator->() const { assert(_p); return _p; }

                private:
                T* _p;
                }; // class ptr<T>


                This is, indeed, the simplest version of any smart pointer that may exist: a type that documents that it does not own the resource it points too.






                share|improve this answer



















                • 7




                  I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
                  – user729124
                  Jul 13 '11 at 8:49








                • 5




                  @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
                  – Matthieu M.
                  Jul 13 '11 at 8:54






                • 1




                  Oh I see. Interesting technique, I'd never have thought of using a class in that way.
                  – user729124
                  Jul 13 '11 at 8:59






                • 1




                  Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
                  – R. Martinho Fernandes
                  Jul 13 '11 at 9:29






                • 9




                  Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
                  – jalf
                  Jul 13 '11 at 9:48














                6












                6








                6






                The use of smart pointers is always recommended because they clearly document the ownership.



                What we really miss, however, is a "blank" smart pointer, one that does not imply any notion of ownership.



                template <typename T>
                class ptr // thanks to Martinho for the name suggestion :)
                {
                public:
                ptr(T* p): _p(p) {}
                template <typename U> ptr(U* p): _p(p) {}
                template <typename SP> ptr(SP const& sp): _p(sp.get()) {}

                T& operator*() const { assert(_p); return *_p; }
                T* operator->() const { assert(_p); return _p; }

                private:
                T* _p;
                }; // class ptr<T>


                This is, indeed, the simplest version of any smart pointer that may exist: a type that documents that it does not own the resource it points too.






                share|improve this answer














                The use of smart pointers is always recommended because they clearly document the ownership.



                What we really miss, however, is a "blank" smart pointer, one that does not imply any notion of ownership.



                template <typename T>
                class ptr // thanks to Martinho for the name suggestion :)
                {
                public:
                ptr(T* p): _p(p) {}
                template <typename U> ptr(U* p): _p(p) {}
                template <typename SP> ptr(SP const& sp): _p(sp.get()) {}

                T& operator*() const { assert(_p); return *_p; }
                T* operator->() const { assert(_p); return _p; }

                private:
                T* _p;
                }; // class ptr<T>


                This is, indeed, the simplest version of any smart pointer that may exist: a type that documents that it does not own the resource it points too.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jul 13 '11 at 9:40

























                answered Jul 13 '11 at 8:21









                Matthieu M.

                201k29269506




                201k29269506








                • 7




                  I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
                  – user729124
                  Jul 13 '11 at 8:49








                • 5




                  @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
                  – Matthieu M.
                  Jul 13 '11 at 8:54






                • 1




                  Oh I see. Interesting technique, I'd never have thought of using a class in that way.
                  – user729124
                  Jul 13 '11 at 8:59






                • 1




                  Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
                  – R. Martinho Fernandes
                  Jul 13 '11 at 9:29






                • 9




                  Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
                  – jalf
                  Jul 13 '11 at 9:48














                • 7




                  I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
                  – user729124
                  Jul 13 '11 at 8:49








                • 5




                  @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
                  – Matthieu M.
                  Jul 13 '11 at 8:54






                • 1




                  Oh I see. Interesting technique, I'd never have thought of using a class in that way.
                  – user729124
                  Jul 13 '11 at 8:59






                • 1




                  Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
                  – R. Martinho Fernandes
                  Jul 13 '11 at 9:29






                • 9




                  Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
                  – jalf
                  Jul 13 '11 at 9:48








                7




                7




                I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
                – user729124
                Jul 13 '11 at 8:49






                I don't see how this is a "smart" pointer. It is a wrapper around a raw pointer that neither shares ownership nor can detect when the pointed-to object has been deleted. What advantage does it offer over a simple raw pointer?
                – user729124
                Jul 13 '11 at 8:49






                5




                5




                @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
                – Matthieu M.
                Jul 13 '11 at 8:54




                @OrbWeaver: functionally ? none. Semantically, however, it makes it clear that ownership was considered, and that it was decided that the variable would not have ownership. When you see a method void foo(Bar*) it is always ambiguous whether or not the method takes ownership of the pointer or not, if you see void foo(client_ptr<Bar>) then you know that it does not take ownership -- though I would be interested in a better name :)
                – Matthieu M.
                Jul 13 '11 at 8:54




                1




                1




                Oh I see. Interesting technique, I'd never have thought of using a class in that way.
                – user729124
                Jul 13 '11 at 8:59




                Oh I see. Interesting technique, I'd never have thought of using a class in that way.
                – user729124
                Jul 13 '11 at 8:59




                1




                1




                Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
                – R. Martinho Fernandes
                Jul 13 '11 at 9:29




                Funny names: not_so_smart_ptr<T>, stupid_ptr<T>, sep_ptr<T>. On a serious note, I think just ptr<T> is ok.
                – R. Martinho Fernandes
                Jul 13 '11 at 9:29




                9




                9




                Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
                – jalf
                Jul 13 '11 at 9:48




                Sounds more like a pointless_ptr<T> to me. A smart pointer guarantees that ownership follows the indicated semantics. This one guarantees nothing, it just indicates that "someone, somewhere, thought that this shouldn't have ownership". Exactly like a raw pointer does. It makes no gaurantee that the program will actually behave like that.
                – jalf
                Jul 13 '11 at 9:48











                3














                One instance where reference counting (used by shared_ptr in particular) will break down is when you create a cycle out of the pointers (e.g. A points to B, B points to A, or A->B->C->A, or etc). In that case, none of the objects will ever be automatically freed, because they are all keeping each other's reference counts greater than zero.



                For that reason, whenever I am creating objects that have a parent-child relationship (e.g. a tree of objects), I will use shared_ptrs in the parent objects to hold their child objects, but if the child objects need a pointer back to their parent, I will use a plain C/C++ pointer for that.






                share|improve this answer

















                • 6




                  Good point, but still that's what weak pointers are for, like boost::weak_ptr
                  – Armen Tsirunyan
                  Jul 13 '11 at 7:56










                • Ah yes, I'd forgotten about weak_ptr.
                  – Jeremy Friesner
                  Jul 13 '11 at 8:09
















                3














                One instance where reference counting (used by shared_ptr in particular) will break down is when you create a cycle out of the pointers (e.g. A points to B, B points to A, or A->B->C->A, or etc). In that case, none of the objects will ever be automatically freed, because they are all keeping each other's reference counts greater than zero.



                For that reason, whenever I am creating objects that have a parent-child relationship (e.g. a tree of objects), I will use shared_ptrs in the parent objects to hold their child objects, but if the child objects need a pointer back to their parent, I will use a plain C/C++ pointer for that.






                share|improve this answer

















                • 6




                  Good point, but still that's what weak pointers are for, like boost::weak_ptr
                  – Armen Tsirunyan
                  Jul 13 '11 at 7:56










                • Ah yes, I'd forgotten about weak_ptr.
                  – Jeremy Friesner
                  Jul 13 '11 at 8:09














                3












                3








                3






                One instance where reference counting (used by shared_ptr in particular) will break down is when you create a cycle out of the pointers (e.g. A points to B, B points to A, or A->B->C->A, or etc). In that case, none of the objects will ever be automatically freed, because they are all keeping each other's reference counts greater than zero.



                For that reason, whenever I am creating objects that have a parent-child relationship (e.g. a tree of objects), I will use shared_ptrs in the parent objects to hold their child objects, but if the child objects need a pointer back to their parent, I will use a plain C/C++ pointer for that.






                share|improve this answer












                One instance where reference counting (used by shared_ptr in particular) will break down is when you create a cycle out of the pointers (e.g. A points to B, B points to A, or A->B->C->A, or etc). In that case, none of the objects will ever be automatically freed, because they are all keeping each other's reference counts greater than zero.



                For that reason, whenever I am creating objects that have a parent-child relationship (e.g. a tree of objects), I will use shared_ptrs in the parent objects to hold their child objects, but if the child objects need a pointer back to their parent, I will use a plain C/C++ pointer for that.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jul 13 '11 at 7:51









                Jeremy Friesner

                38.3k1079159




                38.3k1079159








                • 6




                  Good point, but still that's what weak pointers are for, like boost::weak_ptr
                  – Armen Tsirunyan
                  Jul 13 '11 at 7:56










                • Ah yes, I'd forgotten about weak_ptr.
                  – Jeremy Friesner
                  Jul 13 '11 at 8:09














                • 6




                  Good point, but still that's what weak pointers are for, like boost::weak_ptr
                  – Armen Tsirunyan
                  Jul 13 '11 at 7:56










                • Ah yes, I'd forgotten about weak_ptr.
                  – Jeremy Friesner
                  Jul 13 '11 at 8:09








                6




                6




                Good point, but still that's what weak pointers are for, like boost::weak_ptr
                – Armen Tsirunyan
                Jul 13 '11 at 7:56




                Good point, but still that's what weak pointers are for, like boost::weak_ptr
                – Armen Tsirunyan
                Jul 13 '11 at 7:56












                Ah yes, I'd forgotten about weak_ptr.
                – Jeremy Friesner
                Jul 13 '11 at 8:09




                Ah yes, I'd forgotten about weak_ptr.
                – Jeremy Friesner
                Jul 13 '11 at 8:09











                1














                Few cases, where you may want to use pointers:




                • Function pointers (obviously no smart pointer)

                • Defining your own smart pointer or container

                • Dealing with low level programming, where raw pointers are crucial

                • Decaying from raw arrays






                share|improve this answer





















                • Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
                  – Sebastian Mach
                  Jul 13 '11 at 8:02










                • There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
                  – Jeremiah Willcock
                  Apr 10 '12 at 21:54
















                1














                Few cases, where you may want to use pointers:




                • Function pointers (obviously no smart pointer)

                • Defining your own smart pointer or container

                • Dealing with low level programming, where raw pointers are crucial

                • Decaying from raw arrays






                share|improve this answer





















                • Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
                  – Sebastian Mach
                  Jul 13 '11 at 8:02










                • There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
                  – Jeremiah Willcock
                  Apr 10 '12 at 21:54














                1












                1








                1






                Few cases, where you may want to use pointers:




                • Function pointers (obviously no smart pointer)

                • Defining your own smart pointer or container

                • Dealing with low level programming, where raw pointers are crucial

                • Decaying from raw arrays






                share|improve this answer












                Few cases, where you may want to use pointers:




                • Function pointers (obviously no smart pointer)

                • Defining your own smart pointer or container

                • Dealing with low level programming, where raw pointers are crucial

                • Decaying from raw arrays







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jul 13 '11 at 7:50









                iammilind

                44.4k19124249




                44.4k19124249












                • Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
                  – Sebastian Mach
                  Jul 13 '11 at 8:02










                • There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
                  – Jeremiah Willcock
                  Apr 10 '12 at 21:54


















                • Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
                  – Sebastian Mach
                  Jul 13 '11 at 8:02










                • There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
                  – Jeremiah Willcock
                  Apr 10 '12 at 21:54
















                Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
                – Sebastian Mach
                Jul 13 '11 at 8:02




                Though you can use containers instead of arrays, or smart arrays. Also, why does low-level programming necessitate raw pointers (there are perhaps places, but you did not specify on them)?
                – Sebastian Mach
                Jul 13 '11 at 8:02












                There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
                – Jeremiah Willcock
                Apr 10 '12 at 21:54




                There is something similar to a smart pointer for functions: boost::function or std::function. Those are wrappers that handle copying, etc., for various kinds of function objects, function pointers, etc.
                – Jeremiah Willcock
                Apr 10 '12 at 21:54











                1














                I think a little bit more thorough answer was given here: Which kind of pointer do I use when?



                Excerpted from that link: "Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope." (bold preserved from the original)



                The problem is that if you're writing code for general use it's not always easy to be absolutely certain the object will outlive the raw pointer. Consider this example:



                struct employee_t {
                employee_t(const std::string& first_name, const std::string& last_name) : m_first_name(first_name), m_last_name(last_name) {}
                std::string m_first_name;
                std::string m_last_name;
                };

                void replace_current_employees_with(const employee_t* p_new_employee, std::list<employee_t>& employee_list) {
                employee_list.clear();
                employee_list.push_back(*p_new_employee);
                }

                void main(int argc, char* argv) {
                std::list<employee_t> current_employee_list;
                current_employee_list.push_back(employee_t("John", "Smith"));
                current_employee_list.push_back(employee_t("Julie", "Jones"));
                employee_t* p_person_who_convinces_boss_to_rehire_him = &(current_employee_list.front());

                replace_current_employees_with(p_person_who_convinces_boss_to_rehire_him, current_employee_list);
                }


                Much to its surprise, the replace_current_employees_with() function can inadvertently cause one of its parameters to be deallocated before it's finished using it.



                So even though it might at first seem like the replace_current_employees_with() function doesn't need ownership of it's parameters, it needs some kind of defense against the possiblity of its parameters being insidiously deallocated before it's finished using them. The simplest solution is to actually take (temporary shared) ownership of the parameter(s), presumably through a shared_ptr.



                But if you really don't want to take ownership, there is now a safe option - and this is the shameless plug portion of the answer - "registered pointers". "registered pointers" are smart pointers that behave like raw pointers, except that they are (automatically) set to null_ptr when the target object is destroyed, and by default, will throw an exception if you try to access an object that has already been deleted.



                Also note that registered pointers can be "disabled" (automatically replaced with their raw pointer counterpart) with a compile-time directive, allowing them to be used (and incur overhead) in debug/test/beta modes only. So you should really have to resort actual raw pointers quite rarely.






                share|improve this answer




























                  1














                  I think a little bit more thorough answer was given here: Which kind of pointer do I use when?



                  Excerpted from that link: "Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope." (bold preserved from the original)



                  The problem is that if you're writing code for general use it's not always easy to be absolutely certain the object will outlive the raw pointer. Consider this example:



                  struct employee_t {
                  employee_t(const std::string& first_name, const std::string& last_name) : m_first_name(first_name), m_last_name(last_name) {}
                  std::string m_first_name;
                  std::string m_last_name;
                  };

                  void replace_current_employees_with(const employee_t* p_new_employee, std::list<employee_t>& employee_list) {
                  employee_list.clear();
                  employee_list.push_back(*p_new_employee);
                  }

                  void main(int argc, char* argv) {
                  std::list<employee_t> current_employee_list;
                  current_employee_list.push_back(employee_t("John", "Smith"));
                  current_employee_list.push_back(employee_t("Julie", "Jones"));
                  employee_t* p_person_who_convinces_boss_to_rehire_him = &(current_employee_list.front());

                  replace_current_employees_with(p_person_who_convinces_boss_to_rehire_him, current_employee_list);
                  }


                  Much to its surprise, the replace_current_employees_with() function can inadvertently cause one of its parameters to be deallocated before it's finished using it.



                  So even though it might at first seem like the replace_current_employees_with() function doesn't need ownership of it's parameters, it needs some kind of defense against the possiblity of its parameters being insidiously deallocated before it's finished using them. The simplest solution is to actually take (temporary shared) ownership of the parameter(s), presumably through a shared_ptr.



                  But if you really don't want to take ownership, there is now a safe option - and this is the shameless plug portion of the answer - "registered pointers". "registered pointers" are smart pointers that behave like raw pointers, except that they are (automatically) set to null_ptr when the target object is destroyed, and by default, will throw an exception if you try to access an object that has already been deleted.



                  Also note that registered pointers can be "disabled" (automatically replaced with their raw pointer counterpart) with a compile-time directive, allowing them to be used (and incur overhead) in debug/test/beta modes only. So you should really have to resort actual raw pointers quite rarely.






                  share|improve this answer


























                    1












                    1








                    1






                    I think a little bit more thorough answer was given here: Which kind of pointer do I use when?



                    Excerpted from that link: "Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope." (bold preserved from the original)



                    The problem is that if you're writing code for general use it's not always easy to be absolutely certain the object will outlive the raw pointer. Consider this example:



                    struct employee_t {
                    employee_t(const std::string& first_name, const std::string& last_name) : m_first_name(first_name), m_last_name(last_name) {}
                    std::string m_first_name;
                    std::string m_last_name;
                    };

                    void replace_current_employees_with(const employee_t* p_new_employee, std::list<employee_t>& employee_list) {
                    employee_list.clear();
                    employee_list.push_back(*p_new_employee);
                    }

                    void main(int argc, char* argv) {
                    std::list<employee_t> current_employee_list;
                    current_employee_list.push_back(employee_t("John", "Smith"));
                    current_employee_list.push_back(employee_t("Julie", "Jones"));
                    employee_t* p_person_who_convinces_boss_to_rehire_him = &(current_employee_list.front());

                    replace_current_employees_with(p_person_who_convinces_boss_to_rehire_him, current_employee_list);
                    }


                    Much to its surprise, the replace_current_employees_with() function can inadvertently cause one of its parameters to be deallocated before it's finished using it.



                    So even though it might at first seem like the replace_current_employees_with() function doesn't need ownership of it's parameters, it needs some kind of defense against the possiblity of its parameters being insidiously deallocated before it's finished using them. The simplest solution is to actually take (temporary shared) ownership of the parameter(s), presumably through a shared_ptr.



                    But if you really don't want to take ownership, there is now a safe option - and this is the shameless plug portion of the answer - "registered pointers". "registered pointers" are smart pointers that behave like raw pointers, except that they are (automatically) set to null_ptr when the target object is destroyed, and by default, will throw an exception if you try to access an object that has already been deleted.



                    Also note that registered pointers can be "disabled" (automatically replaced with their raw pointer counterpart) with a compile-time directive, allowing them to be used (and incur overhead) in debug/test/beta modes only. So you should really have to resort actual raw pointers quite rarely.






                    share|improve this answer














                    I think a little bit more thorough answer was given here: Which kind of pointer do I use when?



                    Excerpted from that link: "Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope." (bold preserved from the original)



                    The problem is that if you're writing code for general use it's not always easy to be absolutely certain the object will outlive the raw pointer. Consider this example:



                    struct employee_t {
                    employee_t(const std::string& first_name, const std::string& last_name) : m_first_name(first_name), m_last_name(last_name) {}
                    std::string m_first_name;
                    std::string m_last_name;
                    };

                    void replace_current_employees_with(const employee_t* p_new_employee, std::list<employee_t>& employee_list) {
                    employee_list.clear();
                    employee_list.push_back(*p_new_employee);
                    }

                    void main(int argc, char* argv) {
                    std::list<employee_t> current_employee_list;
                    current_employee_list.push_back(employee_t("John", "Smith"));
                    current_employee_list.push_back(employee_t("Julie", "Jones"));
                    employee_t* p_person_who_convinces_boss_to_rehire_him = &(current_employee_list.front());

                    replace_current_employees_with(p_person_who_convinces_boss_to_rehire_him, current_employee_list);
                    }


                    Much to its surprise, the replace_current_employees_with() function can inadvertently cause one of its parameters to be deallocated before it's finished using it.



                    So even though it might at first seem like the replace_current_employees_with() function doesn't need ownership of it's parameters, it needs some kind of defense against the possiblity of its parameters being insidiously deallocated before it's finished using them. The simplest solution is to actually take (temporary shared) ownership of the parameter(s), presumably through a shared_ptr.



                    But if you really don't want to take ownership, there is now a safe option - and this is the shameless plug portion of the answer - "registered pointers". "registered pointers" are smart pointers that behave like raw pointers, except that they are (automatically) set to null_ptr when the target object is destroyed, and by default, will throw an exception if you try to access an object that has already been deleted.



                    Also note that registered pointers can be "disabled" (automatically replaced with their raw pointer counterpart) with a compile-time directive, allowing them to be used (and incur overhead) in debug/test/beta modes only. So you should really have to resort actual raw pointers quite rarely.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 23 '17 at 12:09









                    Community

                    11




                    11










                    answered Feb 10 '16 at 7:12









                    Noah

                    313




                    313























                        -2














                        It is true. I can not see the benefits of raw pointers over smart pointers, especially in a complex project.



                        For tempory and lightweight usage, raw pointers are fine though.






                        share|improve this answer


























                          -2














                          It is true. I can not see the benefits of raw pointers over smart pointers, especially in a complex project.



                          For tempory and lightweight usage, raw pointers are fine though.






                          share|improve this answer
























                            -2












                            -2








                            -2






                            It is true. I can not see the benefits of raw pointers over smart pointers, especially in a complex project.



                            For tempory and lightweight usage, raw pointers are fine though.






                            share|improve this answer












                            It is true. I can not see the benefits of raw pointers over smart pointers, especially in a complex project.



                            For tempory and lightweight usage, raw pointers are fine though.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Jun 12 '17 at 23:35









                            Trombe

                            1298




                            1298






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6675651%2fwhen-should-i-use-raw-pointers-over-smart-pointers%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Full-time equivalent

                                Bicuculline

                                さくらももこ