1

I don't think I've understood the concept of smart pointers correctly.

Have a look at this MWE:

// Example program
#include <iostream>
#include <memory>
#include <string>

struct P{
    float x, y;
    P() : x(0.f), y(0.f){}
    P(float x, float y) : x(x), y(y){}
    P(P&& q) : x(q.x), y(q.y){}
    P& operator=(P&& q){
        x = q.x;
        y = q.y;
        return *this;
    }
    P& operator=(const P&) = delete;
    P(const P&) = delete;

};

std::ostream& operator<<(std::ostream& out, const P& p){ out << p.x << " / " << p.y; return out;}

int main(){    
    P p1{1.f, 0.f};
    P p2{2.f, 0.f};

    std::unique_ptr<P> p1Ptr(std::make_unique<P>(std::move(p1)));
    P* p2Ptr = &p2;

    p1 = std::move(P{1.f, 1.f});
    p2 = std::move(P{2.f, 2.f});

    std::cout << " p1: " << p1 << "\n";
    std::cout << "*p1: " << *p1Ptr << "\n";
    std::cout << "*p1: " << *(p1Ptr.get()) << "\n";
    std::cout << " p2: " << p2 << "\n";
    std::cout << "*p2: " << *p2Ptr << std::endl; 
}

Output:

p1: 1 / 1
*p1: 1 / 0
*p1: 1 / 0
p2: 2 / 2
*p2: 2 / 2

I would have expected the std::unique_ptr to also see the value change of p1. However, this is not the case. How can I achieve this?

4
  • The pointer p1ptr is pointing to a completely different object of type P. It doesn't point to or reference p1 at all. *p1ptr and p1 are two distinct and separate objects. Commented Jul 2, 2019 at 12:09
  • 1
    note that the moves are redundant, p1 = P{1.f, 1.f}; is already a move assignment. Commented Jul 2, 2019 at 12:21
  • This is XY problem - why do you need std::unique_ptr to point to existing object? It defeats its purpose. Commented Jul 2, 2019 at 12:27
  • @Slava if you are trying to own a struct that doesn't have a ctor defined, then you have no option but to point to an existing object? stackoverflow.com/questions/55141594/… Commented Jan 12, 2022 at 17:15

1 Answer 1

4

p1Ptr does not actually point at the object p1. It points at the unnamed object which was created by std::make_unique using the constructor P(P&&).

It doesn't make sense to have a std::unique_ptr<T> point at an object defined local to a function block. The whole reason for a unique_ptr is that it is the single owner of the object it points at in some way. Since you're using the default deleter, that ownership means that the unique_ptr will delete a pointer to its object, attempting to end its lifetime. But a function local object already has its lifetime "owned" by the function block, and will automatically be destroyed when execution leaves that block; it's not valid to delete a pointer to such an object.

Sign up to request clarification or add additional context in comments.

3 Comments

So if I need pointers to elements in a vector, it is better to use raw pointers?
@infinitezero smart pointers represent ownership, either unique or shared, if you just point but do not own use raw pointers. Btw it is not a good idea to have pointers to elements in a vector due to reallocation.
The elements in a std::vector are similarly already "owned", this time by the vector.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.