Home > database >  I can copy or pass by value unique pointers, how is this possible?
I can copy or pass by value unique pointers, how is this possible?

Time:06-16

What I've read from multiple sources states that, An unique_ptr cannot be copied to another unique_ptr, passed by value to a function, or used in any C Standard Library algorithm that requires copies to be made. However, I can seem to be able to do all those things.

#include <iostream>
#include <memory>

int test(int copy)
{
    std::cout << "copy:        " << copy << std::endl;
    return copy;
}

int main()
{
    std::unique_ptr<int> uniquePtr1(new int(4));
    std::cout << "*uniquePtr1: " << *uniquePtr1 << std::endl;

    int num1 = *uniquePtr1;
    std::cout << "num1:        " << num1 << std::endl;

    int num2 = test(*uniquePtr1);
    std::cout << "num2:        " << num2 << std::endl;

    int *ptr1 = new int;
    *ptr1 = *uniquePtr1;
    std::cout << "*ptr1:       " << *ptr1 << std::endl;

    std::unique_ptr<int> uniquePtr2(new int);
    *uniquePtr2 = *uniquePtr1;
    std::cout << "*uniquePtr2: " << *uniquePtr2 << std::endl;

    delete ptr2;
}
Output:
*uniquePtr1: 4
num1:        4
copy:        4
num2:        4
*ptr2:       4
*uniquePtr2: 4

Am I missing something? Links are also appreciated.

CodePudding user response:

You indeed can't copy a unique pointer, this won't compile:

std::unique_ptr<int> uniquePtr1(new int(4));
std::unique_ptr<int> uniquePtr2(uniquePtr1);

You'd need to move uniquePtr1 into uniquePtr2:

std::unique_ptr<int> uniquePtr2(std::move(uniquePtr1));

What your code is doing is copying the value pointed to by the pointer.

A useful analogy would be a pointer being equivalent to a box and the value of that pointer being a ball in the box. A unique box can't hold the same ball as any other box but it is possible to look at the ball in the first unique box and add a ball of the same colour to another unique box. You now have two unique boxes, both containing red balls but not the same red ball. If you were now to paint one of the balls blue the other ball would still be red.

Expanding this analogy to shared pointers (or bare pointers) requires some balls that can exist in multiple places at the same time. With a shared box you can have the same ball in two different shared boxes and painting one ball will also change the colour of the ball in the other box.

Back to code:

std::unique_ptr<int> uniquePtr1(new int(4));
std::cout << *uniquePtr1; // 4
std::unique_ptr<int> uniquePtr2(new int(*uniquePtr1));
std::cout << *uniquePtr1; // 4
std::cout << *uniquePtr2; // 4
*uniquePtr1 = 5;
std::cout << *uniquePtr1; // 5
std::cout << *uniquePtr2; // still 4

Though uniquePtr1 point to ints with the same value they are separate objects and updating one doesn't update the other.

With shared pointers we can copy the pointer rather than the value:

std::shared_ptr<int> sharedPtr1(new int(4));
std::cout << *sharedPtr1; // 4
std::shared_ptr<int> sharedPtr2(new int(*sharedPtr1)); // copy the value into a new pointer
std::shared_ptr<int> sharedPtr3(sharedPtr1); // copy the pointer
std::cout << *sharedPtr1; // 4
std::cout << *sharedPtr2; // 4
std::cout << *sharedPtr3; // 4
*sharedPtr1= 5;
std::cout << *sharedPtr1; // 5
std::cout << *sharedPtr2; // still 4
std::cout << *sharedPtr3; // 5

CodePudding user response:

You haven't copied any unique_ptr, you're just coping the value it's pointing to.

Try these:

/// (1)
void f(unique_ptr<int>);

unique_ptr<int> p = make_unique(1);
f(p);

/// (2)
unique_ptr<int> p = make_unique(2);
unique_ptr<int> q = p;

The confusion seems to be on what it means to copy, rather than any specific confusion with unique_ptr.

  • Related