C++ how to pass unique_ptr to function and still benefit from polymorphism?

前端 未结 1 1839
一整个雨季
一整个雨季 2021-01-24 14:29

I have the following class definitions:

class A {...}
class B : public class A {...}

and an owner class definition:

class C {
          


        
相关标签:
1条回答
  • 2021-01-24 14:43

    Don't pass unique pointers by mutable reference. You will have bugs such as this one.

    Indeed the solution is to pass by value:

    class C {
        std::unique_ptr<A> a;
    public: 
        C(std::unique_ptr<A> a) { this->a = std::move(a); }
    }
    
    // ...
    
    auto b = std::make_unique<B>();
    C(std::move(b));
    

    This works but feels counter intuitive, because part of the purposes of using unique_ptr instead of shared_ptr is to get that performance increase from not having to copy memory address.

    No. The advantage of unique ptr is that they are a zero overhead abstraction over a pointer with a unique ownership.

    Shared pointer have a cost. Each time they are copied, they are performing atomic ref-count. This hurts the cache and is not a negligible overhead. Also, shared pointer hide who owns who. The number of owners are determined at runtime, which makes the code harder to think about.

    By the way, copying an address has negligible overhead. A reference is most of the time implemented in term of a pointer. Copying a raw pointer has the same cost as passing by reference. Since std::unique_ptr is a zero overhead abstraction, copying (or moving) a unique pointer has the same cost as copying a raw pointer, which in turn is about the same cost as passing by reference. You don't have to worry about the performance of copying pointers.

    But in this case, instead of copying memory address, it's creating a brand new unique_ptr to just pass it by value, only to toss it away after the function goes out of scope.

    Creating a brand new unique_ptr is the same cost as copying a memory address. Unlike other popular languages, C++ object are on the stack by default, offering the same performance as dealing with native types.


    If you worry so much about performance, compile with optimization, profile your code and benchmark. Any statement about performance is meaningless unless you measure it. If you inspected the assembly output of the compiler, you'd notice that they are exactly the same.

    Disclaimer: I did not compile using clang in the live example, because it elided the whole code away even on O2.

    0 讨论(0)
提交回复
热议问题