Different address of std::unique_ptr::get and operator& - c++

Using pointers in the example below gave me a confusion so I probably misunderstand something. I will try to show my way of understanding and some pseudo-simple example.
Creating std::unique_ptr variable of name my_int ensures that it can not be copied and there is only one owner of it's int object. Then I create a vector to storage the pointer and put it without copying with std::emplace_back().
Now I would like to check if the element of vector integers[0] has the same address in memory as the orginal element my_int. I thought it should because this element could not be copied.
Example code:
auto my_int = std::make_unique<int>(1);
std::vector<std::unique_ptr<int>> integers;
integers.emplace_back(my_int.get());
std::cout<< "Value of my_int: " << *my_int << std::endl;
std::cout << "Address of my_int: " << my_int.get() << std::endl;
std::cout << "Also address of my_int: " << &my_int << std::endl;
std::cout << "Also address of my_int: " << &integers[0]<< std::endl;
std::cout << "Also address of my_int: " << integers[0].get()<< std::endl;
Result of test:
Value of my_int: 1
Address of my_int: 0x260fc40
Also address of my_int: 0x65fb58
Also address of my_int: 0x260fe20
Also address of my_int: 0x260fc40
I also tried using std::move() when putting the object to vector but the effect is the same, addresses differs but I don't understand why.
My first confusion is that &my_int and my_int.get() is not the same and the second confusion is that also integers[0].get() differs from &integers[0].

The expression my_int.get() returns a pointer to the contained integer, its type is int*.
The expression &my_int returns a pointer to the my_int object itself, and has the type std::unique_ptr<int>*.
And integers[0] is a distinct and different object from my_int. They just happen to contain the same pointer. This is bad for a unique pointer: together, they will try to free the same memory twice. You must use std::move
auto my_int = std::make_unique<int>(1);
std::vector<std::unique_ptr<int>> integers;
integers.emplace_back(std::move(my_int)); // push_back also works
This way my_int will be set to contain nullptr, and only integers[0] will contain the pointer to the allocated memory.
To understand my_int (or pointers in general really) better you might think of it something like this:
+--------+ +---+
| my_int | --> | 1 |
+--------+ +---+
^ ^
| |
&my_int my_int.get()
It's the same thing with integers[0].get() and &integers[0].

Creating std::unique_ptr variable of name my_int ensures that it can not be copied and there is only one owner of it's int object.
It is only the std::unique_ptr that cannot be copied. But unique pointer cannot guarantee that you won't copy the bare pointer that it owns. Copying the bare pointer owned by the unique pointer is what exactly you did which results in two "unique" owners of the same resource. And that will result in undefined behaviour when the second unique pointer is destroyed.
When you call std::unique_ptr::get, the unique pointer won't release its ownership to you. You should never pass a pointer, that isn't owned by you, into constructor of a smart pointer.
To fix this, you can transfer the ownership from one smart pointer into another by move:
integers.emplace_back(std::move(my_int));
addresses differs but I don't understand why.
The unique pointer variable is one object, and the element of the vector is another object. Since they are separate objects, they have a separate address. Even if they happen to be pointers that point to the same object - the integer, which is yet another object. Those three objects correspond to the three different addresses that you see in the output.

Related

Memory allocation for a variable/s in C++

Hello guys) I would love to get an answer for this question:
Let me share a small portion of code I have written in C++:
#include <iostream>
using namespace std;
int main() {
int* ptr;
int var = 7;
ptr = &var;
cout << "var address:" << &var << endl;
int &ref = var;
cout << "ref address:" << &ref << endl;
cout << "Var value: " << var << endl;
cout << "ref value: " << ref << endl;
return 0;
}
after writing this block of code, I've realized that the addresses that store the variables var and ref are equal. The values these two variables store are the same too. However, I just don't get it in terms of actual numbers of variables the OS memory has allocated for: did the OS allocate memory for ref and var separately or did it allocate only 1 spot in memory for these two(var and ref) variables (if so, does it mean that the spot in memory has two names/identifiers (ref and var)?
I have tried to understand what is actually going on in memory and how does it allocate memory. I wanted to know also how the memory system is actually designed since I cannot comprehend this problem just by drawing box/pointer diagrams.
References are not objects and don't have all the basic properties of object such as storage or size. There may be no storage to get an address to. If you try to get the address or size of a reference, you will instead get the address of the referred object or the size of the referred object.
From https://en.cppreference.com/w/cpp/language/reference :
References are not objects; they do not necessarily occupy storage, although the compiler may allocate storage if it is necessary to implement the desired semantics
So a reference might occupy addressable storage, but only when the implementation needs that storage to implement reference semantics (such as by using a pointer in the background). But this is an implementation detail. It is mostly hidden from the developer, and even then trying to get its address will still give a pointer to the referred object instead.
Note that pointers are objects. They occupy storage, have a size and their address can be obtained with &, just like an int. This is why you observe different behavior with references and with pointers.
In general, references are glorified pointers, that auto-deference on use, can't be changed to point to a different object after being created, and aren't allowed to be null.
In simple cases like this one, the reference will almost surely be optimized away, and every access to ref will be replaced directly with var.
But in general case, they occupy storage like pointers, though you can't easily get the address of that storage, because applying & to a reference returns the address of the target object.

What is difference between "owned pointer" and the "stored pointer" for std::shared_ptr?

As per this documentation, which says (emphasis mine):
http://www.cplusplus.com/reference/memory/shared_ptr/owner_before/
Unlike the operator< overload, this ordering takes into consideration the shared_ptr's owned pointer, and not the stored pointer in such a way that two of these objects are considered equivalent (i.e., this function returns false no matter the order of the operands) if they both share ownership, or they are both empty, even if their stored pointer value are different.
The stored pointer (i.e., the pointer the shared_ptr object dereferences to) may not be the owned pointer (i.e., the pointer deleted on object destruction) if the shared_ptr object is an alias (alias-constructed objects and their copies).
What is the difference between "owned pointer" and the "stored pointer" of std::shared_ptr?
I would be grateful to have some help with this question.
Here is some related code (check http://cpp.sh/27auqq):
// enable_shared_from_this example
#include <iostream>
#include <memory>
struct C : std::enable_shared_from_this<C> {int a; int b; };
int main () {
std::shared_ptr<C> foo, bar;
foo = std::make_shared<C>();
bar = foo->shared_from_this();
std::shared_ptr<int> p1(foo, &foo->a);
std::shared_ptr<int> p2(foo, &foo->b);
*p1=5;
*p2=9;
std::cout << p1.use_count() << std::endl;
std::cout << foo->a << std::endl;
std::cout << foo->b << std::endl;
if (!foo.owner_before(bar) && !bar.owner_before(foo))
std::cout << "foo and bar share ownership" << std::endl;
if(!p1.owner_before(p2) && !p2.owner_before(p1))
std::cout << "p1 and p2 share ownership" << std::endl;
if(!p1.owner_before(foo) && !foo.owner_before(p1))
std::cout << "p1 and foo share ownership" << std::endl;
return 0;
}
Here is the output:
4
5
9
foo and bar share ownership
p1 and p2 share ownership
p1 and foo share ownership
What is the difference between "owned pointer" and the "stored pointer" for std::shared_ptr?
Anytime you use the constructor template< class Y > shared_ptr::shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept;, you have something that shares ownership with r, but dereferences to *ptr.
E.g. after
std::shared_ptr<std::pair<int, double>> pair = std::make_shared<std::pair<int,double>>(1, 2.);
std::shared_ptr<int> i(pair, &pair->first);
pair.reset();
the std::pair<int, double> is kept alive by i
In order to support things like converting a shared_ptr<Derived> to shared_ptr<Base> even when no virtual destructor exists (which is allowed in that case even if it isn't a great idea in general for dynamically allocated classes), and for a few other features, shared_ptr needs to have one pointer to the object designated by each specific instance in that instance, and another one in the control block. The control block is used:
for counting "strong references" (owners of the dynamically allocated used ressource managed by the shared_ptr) and "weak references" (owners of the control block but not of the managed used resource);
to remember what to delete (pointer to the owned object) and how to delete it. The control block holds the exact pointer value that was passed to the original shared_ptr constructor.
Usually that value is used only for the purpose of deletion. Its value is examined (compared) only when you use owner_before. All other functions examine the pointer in each shared_ptr instance, not the pointer in the control block.

scoped pointers and reset

I am playing around with boost scoped pointers and I don't understand this behaviour:
#include <iostream>
#include <boost/scoped_ptr.hpp>
int main()
{
boost::scoped_ptr<int> p{new int{1}};
std::cout << &p << '\n';
p.reset(new int {2});
std::cout << &p << '\n';
return 0;
}
I get the following output:
0x7fff5fbff650
0x7fff5fbff650
Shouldn't the reset function change the address pointed by p?
this is the case if use a scoped array instead of a scoped pointer and print the address pointed by the first element in the code above.
When you do
std::cout << &p << '\n';
you are getting the address of p, not what p points to. To get that you need
std::cout << static_cast<void*>(p.get()) << '\n';
The static_cast<void*>() is not really needed in this example as printing a pointer, other than a char*/const char* will give you its address but I added it to just be safe.
You're taking the address of the scoped_ptr called p. There's only one of them!
If you'd printed &*p or p.get() instead (though prefer (void*)p.get() for sanity) then you'd be printing the address of the thing it currently points to.
This address will always change, because you create the second object (using new) slightly before the first one is destroyed, and objects cannot share addresses.
If you'd done a .reset() first, though, then you may or may not see this address changing, depending on what the innards of new did; objects don't have to have addresses unique to the lifetime of your program, as long as they don't share the address of another object that still exists! However, even then, in practice, to be honest, I'd be surprised if the second dynamically-allocated int wound up at the same address as the first.
You are printing address of object p with is a boost::scoped_ptr.
You should use p.get() to get address of handle object;

Why does same pointer has different addresses

class A{};
void Foo(A *p)
{
std::cout << &p << std::endl;
std::cout << p << std::endl;
}
int main()
{
A *p = new A();
std::cout << &p << std::endl;
std::cout << p << std::endl;
Foo(p);
}
The above program prints the same value for p but different addresses for &p. Can somebody please explain why ?
The above program prints the same value for "p"
This is because one p is a copy of the other, so they both have the same value. The value of a pointer is a memory address where an object is stored so having the same value means pointing to the same object.
A function argument is a copy of the object that was passed to the function †.
but different addresses for "&p". Can somebody please explain why ?
Each p here is a separate variable and a separate object ††. Both objects exist simultaneously. The C++ standard specifies that each currently existing object has a unique address †††, so therefore each p here must have a unique address.
The Unary operator & is the addressof operator, and it returns the memory address where the operand is stored.
† Unless that function argument is a reference. In that case the reference is bound to the passed object. The p argument is not a reference.
†† Pointers themselves are objects. The memory address where a pointer stored is separate from the memory address that is its value which is the memory address of the pointed object.
††† There are exceptions in case of sub-objects, but those exceptions aren't relevant here.
void Foo(A *p)
{
std::cout << &p << std::endl;
std::cout << p << std::endl;
}
When you pass something to Foo() that something is copied into p.So the actual parameter(the something which was passed) is not the same thing as the formal parameter(p here), though they will hold the same value.
Inside Foo(), &p will print address of this formal parameter and not the address of the actual parameter that was passed.
And since the formal and actual parameter hold same value, p prints the same value.
operator & is returns Address of Variable
They are difference variable A *a and Foo(A *a) but they pointing to the same address. It's normally has difference address.
Here is a good description of stack and heap.
What and where are the stack and heap?
A short answer as others have mentioned is that:
p points to the allocated instance of A which is allocated from the heap. It is created with the operator 'new' in your code.
&p is pointing to the memory which p itself occupies.
Just as class A occupies memory (which is allocated from the heap using the 'new' operator) p occupies memory (allocated from the stack since it is a local variable).
this event occures because of copy constructors.
The copy constructor is a constructor which creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to −
-Initialize one object from another of the same type.
-Copy an object to pass it as an argument to a function.(this refer to your problem)
-Copy an object to return it from a function.
p is local variable that contain address of object in heap . and &p is address of p in stack. when we pass p to Foo() because of copy constructor
compiler copy p to new local variable hence we have 2 pointer that both of them refer to same location in heap memory. on of them is original p(actual parameter) and second is unnamed local variable(Formal Parameter) in Foo() method that has been built by copy constructor.
also you could see difference between p an &p in below image.

Does std::move always work as expected?

As I know std::move (same as static_cast<T&&>) casts variable to rvalue and assigns to lvalue, and because of this I think in following code:
int a = 1;
int b = static_cast<int&&>(a);
b and a have the same address, but in VS, it prints different addresses.
int a = 1;
int b = static_cast<int&&>(a);
cout << hex << &a << endl;
cout << hex << &b << endl;
If after this a still points to a different memory location, what is the benefit of using std::move in this case?
Just because you "move" them doesn't mean they will share the same address. Moving a value is a high level abstraction, with basic types like int moving and copying is completely the same, which is happening here. I suggest you read the excellent post on std::move to know what it does and what it's uses are.
No, b is its own object, which is copy initialized from an rvalue reference to another int. This is the same as just copying the referenced object.
Move semantics only shines when the "copying" can be preformed by resource stealing (since we know the other objects storage is about to go, anyway).
For a type like an integer, it's still a plain copy.
There is no benefit of using std::move on an int. In your example you are basically copying the value from a to b.
Move semantics is only meaningfull on resources where you want to transfer ownership, e.g. dynamically allocated memory. Take the std::unique_ptr as an example.
auto ptr = std::make_unique<int>(1);
auto ptrCopy = ptr; // copy will not work compilation error.
auto ptrMove = std::move(ptr);
In the above example ptrMove has taken over the ownership of ptr and ptr is now empty.
When you use std::move in C++ you do not move the object itself, you move the value of the object or its contents. So its address does not change.
Moving is no different from copying with an int. But for a complex type with internal pointers to allocated memory, that memory can be transferred without copying using a std::move (assuming it has been designed to respond to std::move).