Trying to understand the unique_pointer vs raw pointer access
#include <iostream>
#include <memory>
int main() {
int a = 10;
int *x = &a;
int *y = &a;
std::unique_ptr<int> p1 = std::make_unique<int>(a);
std::cout<<*x<<*p1<<*y<<"\n";
// prints 101010
*p1 = 20;
std::cout<<*x<<*p1<<*y<<"\n";
// prints 102010
*x =30;
std::cout<<*x<<*p1<<*y<<"\n";
// 302030
return 0;
}
Output
101010
102010
302030
Program ended with exit code: 0
In the above code x, y,p1 are all pointing to variable a;
so change of value a should have reflected to all the pointers dereferencing .
Please do help me to understand the behaviour I am few of the guys who all are now moving from use of raw pointers to smart pointers.
You're wrong, p1 doesn't point to a.
Instead std::make_unique<int>(a) create a brand new int object and initialize it to the current value of a.
To make p1 point to a you need to do
std::unique_ptr<int> p1(&a);
However that brings with it other problems, like p1 taking over the ownership of &a, and attempting to free that memory when p1 is destructed (which is not possible).
You could use the Boost null_deleter to avoid the last problem.
But I recommend that in most situation you should not look at the smart pointers a simple self-deleting pointers, but instead from an ownership perspective.
The code below is based on MSVC.
Reason
std::make_unique() let you make new object, not reference the parameter
You can find that the unique_ptr p1 gets a different address
int a = 10; // &a = 0x000000bd7d5dfb74
int* x = &a; // x = 0x000000bd7d5dfb74
int* y = &a; // y = 0x000000bd7d5dfb74
std::unique_ptr<int> p1 = std::make_unique<int>(a); // p1._Mypair._Myval2 = 0x00000288fbbd6ba0
std::cout << *x << *y << *p1 << "\n";
*p1 = 20;
std::cout << *x << *y << *p1 << "\n";
*x = 30;
std::cout << *x << *y << *p1 << "\n";
Solution
As Some programmer dude said, use std::unique_ptr<int> p1(&a);
This results that the unique_ptr indicates the same address
int* a = new int(10); // a = 0x0000027411117260
int* x = a; // x = 0x0000027411117260
int* y = a; // y = 0x0000027411117260
std::unique_ptr<int> p1(a); // p1._Mypair._Myval2 = 0x0000027411117260
std::cout << *x << *y << *p1 << "\n";
*p1 = 20;
std::cout << *x << *y << *p1 << "\n";
*x = 30;
std::cout << *x << *y << *p1 << "\n";
FYI, as the unique_ptr p1 will free the memory of a, you do not need to free the memory explicitly.
Related
I am trying basic c program using pointers, Here's my code
#include <stdio.h>
int main()
{
int *p;
for(int i=0;i<10;i++){
*p = &i;
printf("%d",*p);
}
return 0;
}
Output:
main.c:16:12: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
*p = &i;
^
...Program finished with exit code 0
And the value is not printed. Is there any problem in assigning variable i which persists from for loop to pointer?
P is the pointer. Therefore, assign the pointer to it as follows.
p = &i;
Then use it as follows in your code.
#include <stdio.h>
int main()
{
int *p;
for(int i=0;i<10;i++){
p = &i;
printf("%d",*p);
}
return 0;
}
With fix and more C++ style using std::cout for output.
(Why not use printf() in C++)
#include <iostream>
int main()
{
int* p{ nullptr }; // initialize before use.
for (int i = 0; i < 10; i++)
{
p = &i;
std::cout << *p << " ";
}
return 0;
}
Use this code.
It'll work, I think
int* p =NULL;
*p = sizeof(i); // casting int to pointer
Here P is an integer Pointer, And pointer is a variable which store the address of the another variable. So you have to assign the the address of variable (i) to variable (p), like
p=&i;
In this line you are storing the address of i in variable p.
When you point p like, *p it will give you the value present at that address.
#include <stdio.h>
int main()
{
int *p;
for(int i=0;i<10;i++){
p = &i;
printf("%d",*p);
}
return 0;
}
I have a simple code:
void function1(int* A);
void function2(int* A);
int main(int argc, char* argv[]) {
int* A = new int[4];
// Readdressed into function1: A[0] is preserved
A[0] = 21;
function1(A);
cout << "\nA[0] is: " << A[0];
// Result A[0] = 21
// Is not readdressed into function2: A[0] is not preserved
A[0] = 21;
function2(A);
cout << "\nA[0] is: " << A[0];
// Result A[0] = 23
return 0;
}
void function1(int* A) {
A = new int[4];
A[0] = 23;
}
void function2(int* A) {
A[0] = 23;
}
Output:
In the case of function1 output A[0] is 21
In the case of function2 output A[0] is 23
Question:
Why does A-pointer not get (In the first case) an address to a new allocated memory cells where A[0] is 23, and preserve an address where A[0] is 21 instead ?
Unless you pass a reference, parameters are passed by value. Pointers are no different.
void function1(int* A) {
A = new int[4];
A[0] = 23;
}
void function2(int* A) {
A[0] = 23;
}
function1 assigns a new value to A. However, A is a local variable in function1. Assining 23 to the first element of that new array, does not affect the array A was originally pointing to.
function2 gets A passed by value as well. Though, it does not attempt to modify A. It just uses A to write 23 at the adress pointed to by A.
Consider this example which is similar to your function1:
#include <iostream>
int a,b = 0;
void function1(int* p) {
p = &b;
*p = 42;
}
int main() {
std::cout << a << b << "\n";
int* ptr = &a;
function1(ptr);
std::cout << a << b << *ptr << "\n";
}
Output is
00
0420
because after calling function1 ptr in main still points to a. The p = &b; in function1 only affects p which is local to function1.
It's been a while since I've coded anything in C++. While I was trying to help another person as a CIS Tutor, he wanted to know why it's necessary to have an ampersand next to a pointer to an int.
I figured that if you were to pass a pointer by reference and you point to something else, the main knows after you passed that val will equal to whatever you set it equal to.
There will be an example below will demonstrate what I'm trying to say.
Is this correct?
//main function
int variable = 0;
int* val = &variable;
function1(val);
cout << *val << endl;
function2(val);
cout << *val << endl;
//Passing in a pointer with reference.
void function1(int*& value)
{
int variable = 9;
value = &variable;
}
//Passing in a pointer without reference.
void function2(int* val)
{
int variable = 9;
value = &variable;
}
My assumption is that the program will output 9 instead of 8 or 0. I hope this give you guys a clear picture of what I'm trying to ask.
The difference between passing the values and passing the reference is the same with pointers as with other values (actually pointers are nothing special they just hold numbers that sometimes are adresses of other objects).
With int:
void foo(int x) { x = 1; }
void bar(int& x) { x = 2; }
int main() {
int y = 5;
foo(y);
std::cout << y; // prints 5
bar(y);
std::cout << y; // prints 2
}
Now with pointers:
void foo(int* x) { x = 0; }
void bar(int*& x) { x = 0; }
int main() {
int y = 42;
int* z = &y;
foo(z);
std::cout << z; // prints the address of y
bar(z);
std::cout << z; // prints 0
}
Note that your function1 is broken, because when you call it
int* y;
function1(y);
std::cout << *y; // **baaam**
// the value y points to is already gone
the int inside the function ends its lifetime when the function returns and the caller cannot use the value in any meaningful way. Note that in this particular example you would probably get the "correct" value printed, but that is just by coincidence and dereferencing y after passing it to function1 is undefined behaviour.
So I'm trying to familiarise myself with c++ pointers by running the following code.
#include <iostream>
using namespace std;
int main(void){
int* x;
cout << &x << endl;
return 0;
}
which works fine and prints the pointer value of x but
#include <iostream>
using namespace std;
int main(void){
int* x;
*x = 100;
cout << &x << endl;
return 0;
}
gives me a segmentation fault when I try to tun it. Why is this? I don't see how that extra line should change anything about the address of x.
You did not allocate an object which you are going to assign.
int* x;
The value of x is unspecified and can be any arbitrary value. So the next statement
*x = 100;
is invalid.
You have to write
x = new int;
*x = 100;
Or
x = new int( 100 );
Or even
x = new int { 100 };
provided that your compiler supports the list initialization for operator new which was introduced in the C++ 2011..
and prints the pointer value of x but
Not exactly.
std::cout << &x; it prints x's address (the pointer's address);
std::cout << x; prints the address, x points to;
std::cout << *x; prints what x points to;
int* x;
*x = 100;
Here, x is just a pointer, you need to allocate memory for the 100. For example
int* x = new int;
*x = 100;
std::cout << *x;
Or just
int* x = new int( 100 );
std::cout << *x;
Without allocating memory and leaving x uninitialized, by *x = 100 you're trying to change some random memory, which leads to undefined behavior.
You have undefined behaviour.
Your first example is fine since &x (which has type int**) is the address of a stack allocated pointer. One of the << overloads in cout is defined to output that correctly.
In the second example, you are dereferencing a pointer that is not pointing to anything. That's undefined behaviour; hence the crash. If you'd written
int y;
int* x;
x = &y;
*x = 100; /*this means that y is now 100*/
then all would have been well since now x is pointing to something.
I am trying to understang a dynamic array. In this case - an array of pointers.
This program is Ok to me - it is working, everything is fine.
What troubles me is how the array is organized in the heap.
Let us launch it, that will be our example:
pn 00456878
pn[0] 003AFB90
pn[1] 003AFB80
pn[2] 003AFB70
Will you be so kind as to help me understand three matters:
1) Why the address of pn[0] is higher than that of pn[2]? I seemed to have assigned pn[0] before pn[1] and pn[2]?
2) I allocated memory in the heap for 3 elements of sizeof(POINT).
sizeof(POINT) = 8.
003AFB70 + 8 = 3AFB78. Why the next element is 003AFB80?
3) I have formed an opinion that an array in the heap looks as follows:
pn->pn[0]
pn[1]
pn[2]
pn is a base address. The address of pn[0] = base address + 0.
Judging from what I can see here we can conclude that there is a gap between a base address and the first element. Is it for some auxiliarry data or what is it for?
Thank you in advance.
My code is:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct POINT
{
int x;
int y;
};
POINT ** pn;
POINT ** tmp;
int _tmain(int argc, _TCHAR* argv[])
{
int counter = 3;
POINT p_tmp;
cout << "sizeof(POINT): " << sizeof(POINT) << endl;
pn = new POINT * [counter];
POINT a = {0, 0};
POINT b = {1, 1};
POINT c = {2, 2};
pn[0] = &a;
pn[1] = &b;
pn[2] = &c;
cout << "pn "<< pn << endl;
cout << "pn[0] "<< pn[0] << endl;
cout << "pn[1] "<< pn[1] << endl;
cout << "pn[2] "<< pn[2] << endl;
cin.get();
POINT m = * pn[0];
POINT n = * pn[1];
POINT k = * pn[2];
cout << m.x << ","<<m.y<< endl;
cout << n.x << ","<<n.y<< endl;
cout << k.x << ","<<k.y<< endl;
cin.get();
tmp = new POINT * [counter];
memcpy(tmp, pn, (counter * sizeof(POINT)));
for (int i = 0; i < counter; i++)
{
cout << "tmp[" << i << "] "<< tmp[i] << endl;
}
cin.get();
delete[] pn;
pn = tmp;
m = * pn[0];
n = * pn[1];
k = * pn[2];
cout << m.x << ","<<m.y<< endl;
cout << n.x << ","<<n.y<< endl;
cout << k.x << ","<<k.y<< endl;
cin.get();
return 0;
}
Your confusion arises from the fact that your array contains POINT*s and not POINTs.
Why the address of pn[0] is higher than that of pn[2]? I seemed to have assigned pn[0] before pn[1] and pn[2]?
It's not the address of pn[0] that you are printing, it's its value. The address of pn[0] is denoted by &pn[0].
POINT a = {0, 0};
POINT b = {1, 1};
POINT c = {2, 2};
pn[0] = &a;
pn[1] = &b;
pn[2] = &c;
Here you put in pn the addresses of a, b and c, which are POINTS you declared on the stack. The stack grows from upper addresses to lower addresses, therefore &a > &b > &c.
I allocated memory in the heap for 3 elements of sizeof(POINT). sizeof(POINT) = 8. 003AFB70 + 8 = 3AFB78. Why the next element is 003AFB80?
No, you allocated memory in the heap for 3 elements of sizeof(POINT*) (pointer to POINT, which happen to also be 8 bytes). You allocated an array of three pointers on the heap, but the pointees are on the stack.
In the end, your array looks like this:
(some address) pn-> (00456878) pn[0]-> (003AFB90) a
(00456880) pn[1]-> (003AFB80) b
(00456888) pn[2]-> (003AFB70) c
The pointer pn is static memory, but points to 3 pointers on the heap that point back to 3 elements on the stack.
If you wanted to have everything on the heap, you'd do it like this:
Point **pn = new POINT*[counter];
for (int i = 0; i < counter; ++i)
pn[i] = new POINT;
In this layout, the pointer pn is in static memory, but points to 3 pointers on the heap that point to 3 elements on the heap.