CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Jul 2003
    Location
    Kiev, UA
    Posts
    6

    Passing std:: or boost::shared_ptr as a reference to a function

    I was playing with PVS-Studio static analysis tool recently, and it suggested me to replace passing of const std::shared_ptr<type> arg to const std::shared_ptr<type>& arg.

    I perfectly understand that it is a good way to optimize performance as when I pass shared_ptrs by value there are increments / decrements of reference counters which are interlocked operations.

    So the question is - is there any reason I should not do such optimization? Is there any corner case I did not consider?

    I'm now trying to see it is makes sense to optimize this way one heavily-used interface, so would appreciate comments.

  2. #2
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    References are often implemented as pointers by the compiler (although this is not required). If they are, then every dereference within that function will incurr an extra indirection cost.

    This is most likely not significant compared to the cost of copying the shared_ptr, but depending on your usage it's possible it could be. You will need to profile your code both ways to find out.

  3. #3
    Join Date
    Jul 2002
    Posts
    2,543

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    If the function does not store the pointer somewhere for a future use, just pass plain pointer to it.

  4. #4
    Join Date
    May 2009
    Posts
    2,413

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    Quote Originally Posted by Fahrenheit View Post
    So the question is - is there any reason I should not do such optimization? Is there any corner case I did not consider?
    If you do this you no longer have a perfectly fine smart pointer. It may cause the problems you wanted to avoid by introducing a smart pointer in the first place. You've planted a mine ready to go off. It beats the purpose of using smart pointers.

    If you really need this optimization I suggest you instead pass the object the smart pointer points to by const reference, like
    Code:
    void foo(const type& arg);
    //
    std::shared_ptr<type> p;
    //
    foo(*p);
    It's assumed that foo is a low-level function/method that has been identified as a performance bottleneck. It should also be inlined.

    It's also a good idea to reconsider whether you really need this smart pointer. If it's used very locally in low-level performance sensitive code and the ownership is perfectly clear it may be overkill.
    Last edited by nuzzle; March 30th, 2012 at 12:27 AM.

  5. #5
    Join Date
    Jul 2003
    Location
    Kiev, UA
    Posts
    6

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    Lindley, sure, I will yet check out which is actually faster with some benchmark. It is really interesting question. Btw, even if they will tie on single-threaded test in multi-threaded reference to shared_ptr will still be the winner due to less interference with other threads.

    Nuzzle, what kind of mine you are talking about? I understand what in this case I will get two copies of the object (one up the stack, and one down the stack) for only 1 reference count, but I can't think of any specific scenario that will break under these circumstances (synchronous call to some function)

  6. #6
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    Quote Originally Posted by Fahrenheit View Post
    what kind of mine you are talking about?
    I cannot speak for nuzzle, but given that it makes no sense to pass a shared_ptr to a function not supposed to store somewhere a copy ( both in terms of efficiency and semantics ), I wonder in what reasonable scenario a function that acts by propagating ownership of an object to other objects happens to be in performance sensitive code.

    For example, consider an high performance algorithm passing back and forth shared pointers to objects between, say, a number of containers; I think you can always refactor the algorithm in such a way to use plain pointers during calcualtions mantaining a central repository of unique or shared smart pointers to be cleaned/mantained strictly before or after the algorithm performance sensitive core. Moreover, I think such a refactoring would be actually cleaner, being more correct from a semantical POV.

    Quote Originally Posted by Lindley
    If they are, then every dereference within that function will incurr an extra indirection cost.
    note that a function taking a const share_ptr& can always immediately make a copy from it, hence avoiding such an issue, especially if the function is inlined. The same flexibility cannot be said for a function taking a shared_ptr directly.

  7. #7
    Join Date
    Jul 2003
    Location
    Kiev, UA
    Posts
    6

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    I was thinking more about it, and if the function that gets that const shared_ptr<T>& as argument wants to store it somewhere for future use it is absolutely legal, as the stored copy will get its own reference counted.

    Of course if the stored copy is, again, a reference then it won't - but this is a bad design decision to store a reference to some external object - give or take share_ptr

    Also - I did more or less realistic benchmark of passing shared_ptr, and following are my conclusions:
    1) Passing by reference is about 10 times faster than passing by value
    2) Similar cost ratio is for both std::shared_ptr and boost::shared_ptr, but boost's smart pointer is about 15&#37; faster when passed by value
    3) It doesn't matter if the object was created with new T(), or with make_shared<T>() - performance numbers are the same

  8. #8
    Join Date
    May 2009
    Posts
    2,413

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    Quote Originally Posted by nuzzle View Post
    If you do this you no longer have a perfectly fine smart pointer.
    I've changed my mind on this topic. It's perfectly fine to pass a shared_ptr by const reference. In fact it's even best practice.

    If the code is sequential or if it's concurrent and properly synchronized it doesn't matter whether you pass by value or by const reference. Both are correct and will work equally fine. So the choise becomes a matter of which is most efficient and it will be const reference.

    From a purely conceptual standpoint it still makes sense to treat a shared_ptr exactly like a bald pointer that is passing it by value. But since also a bald pointer would be passed by const reference if that were faster I see no reason why a shared_ptr couldn't be passed by const reference now that this actually is faster. It's the same consideration one makes for any type when deciding how to pass it.

    For an excellent clarification of this issue by three top C++ experts see here,

    http://channel9.msdn.com/Shows/Going...sk-Us-Anything

    It's at [04:34] into the discussion.

    In my view knowing that a shared_ptr can be passed efficiently by const reference without causing any harm to the integrity of a program makes it an even better choise over bald pointers. This is always true in sequential code and it's true in concurrent code as long as the shared_ptr implementation sports an atomic reference counter and the code is also otherwise properly synchronized.
    Last edited by nuzzle; June 18th, 2012 at 03:56 AM.

  9. #9
    Join Date
    Jul 2003
    Location
    Kiev, UA
    Posts
    6

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    Quote Originally Posted by nuzzle View Post
    I've changed my mind on this topic. It's perfectly fine to pass a shared_ptr by const reference. In fact it's even best practice.
    Thanks for posting details. Now it feels better as everyone agrees (and this is backed up such C++ gurus on channel 9 video)

  10. #10
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Passing std:: or boost::shared_ptr as a reference to a function

    Quote Originally Posted by nuzzle View Post
    I've changed my mind on this topic. It's perfectly fine to pass a shared_ptr by const reference. In fact it's even best practice.
    IMO, if it has a constructor, you pass it by const_reference. Simple as that.

    If the function then wants to do something mutable with the object, it's the function's own job to create a copy locally. The function signature shouldn't burden the caller with such petty detail.

    That said, passing a shared_ptr by const reference doesn't prevent you from mutating the targeted object anyways, it just prevents you from re-seating it.

    BTW, most algorithms will swap their objects (and even move them in C++11). AFAIK, there is no extra cost to do this operation on shared_ptr over a naked one.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured