5

I have a class that has a setter method which takes a unique_ptr as an argument. That unique_ptr is saved as a class member.

class TestClass {
    std::unique_ptr<Tester> sp;

    void setTester_Way1(std::unique_ptr<Tester> te) {
         auto deleter=std::move(sp);
         sp=std::move(te);
    }

    void setTester_Way2(std::unique_ptr<Tester> te) {
         sp=std::move(te);
    }
};

Which way is the correct way to set the smart pointer? Does Way2 leak the original pointer of sp?

Barry
  • 286,269
  • 29
  • 621
  • 977

2 Answers2

5

Way2 is fine, when you assign to a unique_ptr any existing owned pointer will be safely deleted.

Chris Drew
  • 14,926
  • 3
  • 34
  • 54
1

As Chris Drew said Way2 is fine. One thing though is that unique_ptr is not copyable/assignable so the only ways to pass a unique_ptr is by reference, r-value reference or by value with move(). Trying to do:

int main()
{
    TestClass t;
    auto p = std::make_unique<int>(10);
    t.setTester_Way2(p);
}

Will fail to compile. Although you can move() p into the function(example).

If you change setTester_Way2() to void setTester_Way2(std::unique_ptr<int>& te) then it will compile. If you change the function to take an rvalue reference and std::move() the pointer into the funcnction:

class TestClass {
    std::unique_ptr<int> sp;
public:

    void setTester_Way1(std::unique_ptr<int> te) {
         auto deleter=std::move(sp);
         sp=std::move(te);
    }

    void setTester_Way2(std::unique_ptr<int>&& te) {
         sp=std::move(te);
    }
};

int main()
{
    TestClass t;
    auto p = std::make_unique<int>(10);
    t.setTester_Way2(std::move(p));
}

Then it will also compile.

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 2
    Are you suggesting they _should_ be passing by reference instead? Because I think pass-by-value [is fine](http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/) in this case. – Chris Drew Jul 23 '15 at 14:44
  • @ChrisDrew I personally like by r-value reference as it makes it clear that you are going to move it. Unless I still am of base on move semantics. – NathanOliver Jul 23 '15 at 14:46
  • 5
    pass by r-value reference _does not_ make it clear you are going to move it. It is just a reference, it is not moved until the function decides to move it, it may not. By by value _guarantees_ it will be moved, there is no other way of getting the parameter in there – Chris Drew Jul 23 '15 at 14:50
  • 1
    Anyway, there are many arguments for and against pass-by-value for `unique_ptr` just see the comments on [this blog post](http://scottmeyers.blogspot.co.uk/2014/07/should-move-only-types-ever-be-passed.html)! I think the jury is still out. – Chris Drew Jul 23 '15 at 14:54
  • @ChrisDrew I just fell that if a function takes an r-value reference then it is saying that I may do something I may not but since it is an r-value I can do whatever I want so don't complain if something happens. – NathanOliver Jul 23 '15 at 14:56
  • Think about it, passing a `unique_ptr` by reference is like passing a pointer to pointer. No reason to do that unless you want to modify the pointer itself. One use case is when the function that takes an `unique_ptr` *might or might not* take the ownership of the pointed object. Then passing by rvalue-reference would be advisable. – sbabbi Jul 23 '15 at 23:12