A unique pointer cannot change the value of the original object?

In summary: Then the console prints 3, as I had wanted, but then the program crashes. There is obviously something about unique pointers (and shared pointers in general) that I am not understanding. I'd appreciate some help.Maybe the compiler has treated x as a constant value and replaced usages of it by a constant.In summary, when a built-in pointer is used in place of a unique_ptr, the built-in pointer will point to a memory address that contains the same value as the unique_ptr pointer. When the code prints 3 to the console, this means that the built-in pointer that is in q points to an object that was indeed changed to point to a memory address that contains 3 in
  • #1
JonnyG
234
45
When I run this simple code:

C++:
int main() {
    int x = 45;
    std::unique_ptr<int> q(new int (x));
    *q = 3;
    cout << x << endl;
    
}

45 is printed on the console. I expected this to print 3 to the console. It prints 3 when I use a built-in pointer. Does this mean that unique pointer doesn't actually point to x itself (i.e. doesn't hold x's memory address)? If in the above code I add this line to the end:

cout << *q.get();

Then it prints 3 to the console. This means that the built-in pointer that is in q points to an object that was indeed changed to point to a memory address that contains 3 in it (but this pointer was supposed to point to x!).

Furthermore, when I run this:

C++:
int main() {
    int x = 45;
    int *p = &x;
    std::unique_ptr<int> q(p);
    *q = 3;
    cout << x << endl;
    
}

Then the console prints 3, as I had wanted, but then the program crashes. There is obviously something about unique pointers (and shared pointers in general) that I am not understanding. I'd appreciate some help.
 
Technology news on Phys.org
  • #2
Maybe the compiler has treated x as a constant value and replaced usages of it by a constant.

In the q(p) shouldn't that be q(*p) ?

This stack discussion may help:

https://stackoverflow.com/questions/16894400/how-to-declare-stdunique-ptr-and-what-is-the-use-of-it

Here's a brief tutorial on unique_ptr usage:

https://thispointer.com/c11-unique_ptr-tutorial-and-examples/

They have an example of using ( new int(3) ) which creates a pointer to a location containing three.

So in your case the compiler replaced x by 25 (call by value) stored 25 somewhere and provided a pointer to the 25 instead. Changing x then wasn't reflected in the unique_ptr.

Using a debugger on your code would confirm that.
 
Last edited:
  • #3
jedishrfu said:
In the q(p) shouldn't that be q(*p) ?

I get a compilation error when I run that, but I think I figured out the problem. When I type new int(x) (in q's constructor), this constructs a pointer to an integer of value 45 that has been dynamically-allocated in the heap. This doesn't mean that the dynamically-allocated built-in pointer is pointing to x - it's just pointing to some memory address that also has the value of 45 in it. This is why I cannot change the value of x through q. This is different than me typing:

C++:
int x = 45;
int* p = &x;
std::unique_ptr<int> q(p);

This code first constructs a built-in pointer on the stack that is then passed to the unique_ptr constructor. But the unique_ptr constructor requires a dynamically-allocated pointer, which is why the above code crashes.

At least that's what I think. I will take a look at the tutorial you linked and see if I can confirm this.
 
  • #4
Yeah, I think you're right.

It's the call by value scheme used by C/C++ in method calls.

The x value is placed on the stack and the new int() is called, it pops the value and then allocates memory for it from the heap (it must do this because stack data is volatile) and returns a pointer to the heap value.
 
  • Like
Likes JonnyG
  • #5
jedishrfu said:
Yeah, I think you're right.

It's the call by value scheme used by C/C++ in method calls.

The x value is placed on the stack and the new int() is called, it pops the value and then allocates memory for it from the heap (it must do this because stack data is volatile) and returns a pointer to the heap value.

Now I see that to change the value of the object that my unique_ptr q is pointing to, I must write:

*q.get() = whatever value

I can only access the built-in pointer that q is wrapped around by using the get() method.
Thank you for your help.
 
  • #6
jedishrfu said:
In the q(p) shouldn't that be q(*p) ?
I don't believe so. I see at least 5 constructors for the unique_pointer template class, all of which have a pointer parameter or no parameters at all.

JonnyG said:
When I run this simple code:

C++:
int main() {
    int x = 45;
    std::unique_ptr<int> q(new int (x));
    *q = 3;
    cout << x << endl;
   
}

45 is printed on the console. I expected this to print 3 to the console. It prints 3 when I use a built-in pointer. Does this mean that unique pointer doesn't actually point to x itself (i.e. doesn't hold x's memory address)? If in the above code I add this line to the end:

cout << *q.get();

Then it prints 3 to the console. This means that the built-in pointer that is in q points to an object that was indeed changed to point to a memory address that contains 3 in it (but this pointer was supposed to point to x!).

Furthermore, when I run this:

C++:
int main() {
    int x = 45;
    int *p = &x;
    std::unique_ptr<int> q(p);
    *q = 3;
    cout << x << endl;
   
}

Then the console prints 3, as I had wanted, but then the program crashes. There is obviously something about unique pointers (and shared pointers in general) that I am not understanding. I'd appreciate some help.
I haven't explored the various kinds of "smart" pointers much, so can't enlighten you with regard to what you don't understand. At any rate, your code doesn't crash for me, using VS 2017.

My code adds an include directive and scope operators on cout and endl, but is otherwise the same as yours:
C++:
#include<iostream>
int main() 
{
    int x = 45;
    int *p = &x;
    std::unique_ptr<int> q(p);
    *q = 3;
    std::cout << x << std::endl;
}
 
  • Like
Likes jedishrfu
  • #7
JonnyG said:
When I run this simple code:

C++:
int main() {
    int x = 45;
    std::unique_ptr<int> q(new int (x));
    *q = 3;
    cout << x << endl;

}

new int( x ) allocates space on the heap to store an int, and initializes that int to the value of x, and returns a pointer to the address of the newly allocated int (which is different than the address of x).

JonnyG said:
C++:
int main() {
    int x = 45;
    int *p = &x;
    std::unique_ptr<int> q(p);
    *q = 3;
    cout << x << endl;

}

In this example, you do create a smart pointer with the address of x. But smart pointers delete the pointer they manage when they go out of scope (in their destructor). x itself is an automatic object on the stack that is destroyed when the function exits. q also goes out of scope, so x is 'destroyed' and also delete is called on its address. That's why it crashes.

Anyways, it never makes sense to call delete on the address of a stack object.
 
Last edited:
  • Like
Likes jbunniii, JonnyG and jedishrfu
  • #8
Good explanation @Jarvis323. My version did throw an exception, but only after the final brace, which I didn't check for in the debugger.
 
  • Like
Likes Jarvis323 and jedishrfu

FAQ: A unique pointer cannot change the value of the original object?

What is a unique pointer?

A unique pointer is a type of smart pointer in the C++ programming language that is used to manage dynamically allocated memory. It ensures that only one pointer can point to a particular object at a time, preventing multiple pointers from accidentally accessing or modifying the same object.

Why can't a unique pointer change the value of the original object?

A unique pointer is designed to have exclusive ownership of the object it points to. This means that it is the only pointer that has the ability to access and modify the object's data. If the value of the original object were to be changed by another pointer, it could lead to unexpected behavior and potential memory leaks.

What happens if I try to use a unique pointer to change the value of the original object?

If you try to use a unique pointer to change the value of the original object, the compiler will throw an error. This is because unique pointers have a "const" modifier, meaning they are not allowed to modify the object's value. This is a safety measure to prevent unintended changes to the object's data.

Can I use a unique pointer to change the value of an object if I really need to?

No, you should not use a unique pointer to change the value of an object. Unique pointers are not meant to be used for modifying objects, but rather for managing their memory. If you need to change the value of an object, you should use a different type of pointer, such as a raw pointer or a shared pointer.

Are there any alternatives to using a unique pointer for managing memory?

Yes, there are other types of smart pointers available in C++ such as shared pointers, weak pointers, and raw pointers. Each type has its own specific use case and benefits, so it is important to understand their differences and choose the appropriate one for your situation.

Back
Top