For example, I have the following codes:
int a = 1;
int b = 2;
int *c = &a;
int &d = *c;
c = &b;
d++;
What is behaviour of line 4? If i want a reference to a pointer,is it correct to use
int *&e = c;
Is there any reason why to choose a reference to a pointer?
This declaration
int &d = *c;
declares a reference that refers the object pointed to by pointer c.
When this declaration was executed pointer c pointed to object a
int *c = &a;
So the referecne d refers object a. References may not be reassigned. They shall be initialized when they are declared.
Thus the expression in statement
d++;
increases object a.
You may declare a reference to a pointer.
This declaration
int *&e = c;
is valid.
Constant references can be bound to a temporary object. You may not take an address of a temporary object. Refrences alow to use more simple expressions.
Consider for example a simplified function swap that swaps two integers.
Using pointers the function would look like
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
and it could be called like
int a = 5;
int b = 10;
swap( &a, &b );
Using references you could write the function the following way
void swap( int &a, int &b )
{
int tmp = a;
a = b;
b = tmp;
}
and its call would look simpler than the call of the function with pointers.
int a = 5;
int b = 10;
swap( a, b );
regarding the meaning of line 4
int a = 1;
int*c = &a; // okay: pointer to int, points to a
int&d = *c; // okay; reference to int, refers to *c=a;
A reference to a pointer is useful as argument to a function that may alter its value (=address pointed to), for example
void allocate(int*&p)
{ p=new int[10]; }
Related
I'm happy to post my first question here .
so i was play a little bit with pointers to understand the concept and i found this error
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
here is the code :
#include <iostream>
using namespace std;
int main(){
int* pa,pb,pc,a,b,c;
pa = &a;
cin >> a;
cout <<"the value of a :"<<a<<endl;
cout <<"the value of pointer of a :"<<*pa<<endl;
// the problem begins when reading values of b :
pb = &b; //<== error
cin >> b;
cout << "the value of b : "<<b<<endl;
cout <<"the value of pointer of b" <<*pb<<endl;
return 0;
}
i don't know why it went successfully with variable a but failed with the same syntax in b ?
EDIT : thanks for everyone , i know this question is very simple but i've learned from you :)
The * binds to the variable name, not the type. So what you really want is:
int *pa,*pb,*pc,a,b,c;
In the declaration
int* pa,pb,pc,a,b,c;
Only pa is declared as int*. The other variables are declared as int.
You would need to declare the variables as
int *pa, *pb, *pc, a, b, c;
A common recomendation is to declare one variable per line (see for example ES.10: Declare one name (only) per declaration), because * belongs to the variables, not the type and this can be confusing. Your
int* pa,pb,pc,a,b,c;
is actually
int* pa;
int pb;
int pc;
int a;
int b;
int c;
But you wanted:
int* pa;
int* pb;
int* pc;
int a;
int b;
int c;
In other words, you get the error becaue in your code pb is an int but &b is an int*. The first assignment is ok, because pa is a pointer.
Another common recommendation is to always initialize your variables (see ES.20: Always initialize an object), so even nicer would be
int a = 0;
int b = 0;
int c = 0;
int* pa = &a;
int* pb = &b;
int* pc = &c;
And once you got it straight what type pa, pb and pc are you can use auto to get "just the right type":
auto a = 0; // 0 is an integer literal of type int
auto b = 0;
auto c = 0;
auto* pa = &a; // auto would be fine too, &a is a int*
auto* pb = &b;
auto* pc = &c;
I'm studying pointer and reference parts and having very hard time to study them.
I think I understand now some simple usage of reference and pointers in the function, but there is something I cannot totally understand.
Here are some variable declarations:
int a = 1;
float b = 2;
int* p = &a;
string s = "Hello";
vector<int*> values = {p};
What will be the types of the following expressions?
&a
&b
p
&p
&s
&(s.at(1))
values.at(0)
&(values.at(0))
&values
I have no idea what their types exactly are, but I tried it myself.
&a : pointer to int
&b : pointer float
p : pointer to int
&p : pointer to pointer to int
&s : pointer to string
&(s.at(1)) : pointer to string
values.at(0) : pointer to int
&(values.at(0)) : pointer to pointer to int
&values : pointer to pointer to int
and one more problem >
write the following variable declarations:
a) A pointer to a string
b) A reference to a float
c) An array of pointers-to-ints.
d) A pointer to a pointer to bool
e) A reference to a pointer to an int
and my answers are:
a: string* s = "Hello"
b: float& f = g;
c: int n =1;
int*x =&n;
int arr[] = {*x};
d: bool y = true;
bool* x = &y;
bool** qq = &x;
e: int a = 1;
int* x = &a;
int& z = *x;
I'm not sure about my answers. Please help these confusing parts.
First, a std::string is a complex object that contains a char array but it is definitely not a char array. And a std::vector<int> is also a complex object that contains an array of ints.
That means that for the first part some of your tries are wrong:
&(s.at(1)) : pointer to string WRONG: pointer to char
values.at(0) : pointer to int OK
&(values.at(0)) : pointer to pointer to int OK
&values : pointer to pointer to int WRONG: pointer to `vector<int>`
For the second part, as a string is not a char array, you cannot initialize a pointer to string with a litteral char array
string *s = "hello"; WRONG syntax error
You must first create a string and then create a pointer to it
string s = "hello"; OK std::string initialized from a const char *
string *ps = &s; OK pointer to std::string
c is wrong too int arr[] declares an array of int. You must write:
int *arr[] = { x }; OK array of 1 pointers initialized from x which is a pointer to int
For e, int&z = *x; declares a reference to int initialized as a ref to a. To get a ref to a pointer, you must write:
int *&z = x; OK ref to a pointer to int initialized as a ref to x
Part 1:
If the expression e has type T, the type of &e is pointer to T; T*.
Consider the types of the expressions s.at(1) and values more carefully.
Part 2:
c: int arr[] is not "array of pointers-to-ints", it's "array of int".
An array of T is T arr[]; an array of int* is int* arr[].
int n = 1;
int* arr[] = {&n};
e: int& z is not "reference to a pointer to an int", it's "reference to int".
A reference to T is T&; a reference to int* is int*&.
int a = 1;
int* x = &a;
int*& z = x;
If you need to know the exact type of an expression and if you can use Boost, it provides a great functionality.
#include <boost/type_index.hpp>
#include <iostream>
#include <string>
#include <vector>
#define TYPE(x) std::cout << "decltype(" << #x << ") == " << type_id_with_cvr<decltype(x)>().pretty_name() << std::endl
int main()
{
using boost::typeindex::type_id_with_cvr;
int a;
TYPE(a);
int * p = &a;
TYPE(p);
TYPE(&p);
std::vector<int*> values {p};
TYPE(values.at(0));
TYPE(&(values.at(0)));
TYPE(&values);
}
If you can't use Boost, you can still deliberately create a template error to force the compiler to show you the type of expressions (from a talk of Scott Meyers, a great expert of C++).
#include <iostream>
#include <string>
#include <vector>
template <typename T>
class TD;
template <typename T>
void function(T & param)
{
TD<T> templateType;
TD<decltype(param)> paramType;
}
int main()
{
int a;
function(a);
int * p = &a;
function(p);
function(&p);
std::vector<int*> values {p};
function(&values);
}
c) An array of pointers-to-ints
You created an array of int containing a single value, the value to wish the pointer refers to. As said previously, you need a int* [] array.
&(values.at(0)) : pointer to pointer to int OK
Why &(values.at(0)) is a pointer ?
Pointer is variable that contains address in memory
Pointer has its type
unsigned long ip = 0xC0A80A01; // 192.168.10.1
unsigned char *p = (unsigned char *)&ip;
printf("%d.%d.%d.%d\n", p[3], p[2], p[1], p[0]);
// Result: 192.168.10.1
I think it is only takes address of variable.
int a = 1;
int *p = &a;
&a is not a pointer
p is a pointer
Is it?
and
int &refVar = a;
refVar is reference
The following code is one that I written for myself in order to test how pointers and vectors work.
I am very new to C++.
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
//Create the integer pointer vector, and clean it to initialize
vector<int *> lol;
lol.clear();
//Create the pointers and point them to 1,2,3
int a1=1, a2=2, a3=3;
int* a, b, c;
a=&a1;
b=&a2;
c=&a3;
//Put the pointers into the vector
lol.push_back(a);
lol.push_back(b);
lol.push_back(c);
//Return the value of the middle pointer
cout << *lol[1];
}
I get a whole wall of errors while compiling.
Can anyone help? Bear in mind I can only understand novice.
The problem is with this line:
int* a, b, c;
a is int*, but b and c are just ints.
int *a, *b, *c;
Would make it all int*s.
int* a;
int* b
int* c;
does the same thing, but with clearer intentions of declaring three int*s.
See: Placement of the asterisk in pointer declarations
UPDATE: Even better:
int* a = &a1;
int* b = &a2;
int* c = &a3;
Whenever you can, don't separate variable initialization and its declaration.
When declaring multiple pointers on one line, you have to specify the * symbol in front of each pointer variable.
int * a, b, c;
should be :
int *a, *b, *c;
The line :
int * a, b, c;
is interpreted as :
int *a;
int b;
int c;
If you declare variables, do not declare multiple variables on the same line.
What you thought you did was to declare three pointers to int. What you did, was to declare three ints, one of them a pointer:
int* a, b, c;
means
int *a; int b; int c;
Think of the * as belonging to the variable name. Unintuitive, but that's the way the language works.
You want to declare all of the three as pointers:
int* a;
int* b;
int* c;
Change this
int* a, b, c;
to
int *a, *b, *c;
In your declaration you are declaring
a as pointer to int
b as int
c as int
The main problem, as others already noted, are the definitions here:
int* a, b, c;
Basically, only a is an int *; b and c are just ints.
It's just better to have one variable definition per line:
int* a = &a1;
int* b = &a2;
int* c = &a3;
If you use these raw pointers, and if for some reason you want to first define them and then assign their values later, consider at least initializing them to nullptr (or NULL if you are using C++98/03):
// Initialize to NULL/nullptr, to avoid pointers pointing to junk memory
int* a = nullptr;
int* b = nullptr;
int* c = nullptr;
....
// assign proper values to pointers...
Moreover, there are also other notes that can be made for your code:
int main(void)
Since this is C++ - not C - you can omit the (void), and just use () instead:
int main()
When you create the vector:
vector<int *> lol;
lol.clear();
you don't need to call its clear() method after the vector definition: in fact, vector's default constructor (implicitly called by the compiler when you defined the vector in the first line) has already initialized the vector to be an empty vector.
This is just fine:
vector<int *> lol; // Creates an empty vector
Considering these notes, your code can be written something like this:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int *> lol;
int a1 = 1;
int a2 = 2;
int a3 = 3;
int * a = &a1;
int * b = &a2;
int * c = &a3;
lol.push_back(a);
lol.push_back(b);
lol.push_back(c);
cout << *lol[1] << endl;
}
First problem is at declaration of pointers
int* a, b, c;
This will create a as pointer and b & c as int.
Use declaration like
int* a,*b,*c;
And While accessing the elements of vector use .at() method of vector.
cout << *lol.at(0) << endl;
I just wanted to clarify something, imagine we have the function signature:
1) int* X(){}
2) int Y(){}
3) int& Z(){}
I am trying to work out the exhaustive possibilities of types of values I can return for the above. The below show possible implementations for the above function bodies:
1)
int* X(){
int* b = new int(6);
return b;
}
2)
int Y(){
int b = 6;
return b;
}
or
int Y(){
int* b = new int(6);
return *b;
}
EDIT: 2) not good because of memory leak if b isn't deleted.
3)
int& Z(){
int b = 6;
return b;
}
EDIT: 3) not good because b will go out of scope once function returns.
Is there anything I have missed out which could be returned from any of the above 3 function signatures? Getting a bit more adventurous, what about:
int* X(){
int b = 6;
return reinterpret_cast<b>;
}
and
int X(){
int* b = new int(6);
return reinterpret_cast<b>;
}
? (My understanding of reinterpret_cast may be wrong...)
int Y(){
int* b = new int(6);
return b*;
}
This has a syntax error. To dereference b, you would do *b. Nonetheless, this is a very bad implementation because it leaks memory. The dynamically allocated int will never be destroyed.
int& Z(){
int b = 6;
return b;
}
This is also bad because you are returning a reference to a local variable. The local variable b will be destroyed when the function returns and you'll be left with a reference to a non-existent object.
int* X(){}
when you have to return address which is pointing to integer
int Y(){}
for returning simple integer
int& Z(){}
this is something different,
you don't have any argument in Z() thus it is useless.
It must be like
int& Z(int &a)
{
//code body
return (a);
}
and return this to reference variable
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int i1 = 0;
int i2 = 10;
const int *p = &i1;
int const *p2 = &i1;
const int const *p3 = &i1;
p = &i2;
p2 = &i2;
p3 = &i2;
cout << *p << endl
<< *p2 <<endl
<< *p3 <<endl;
return 0;
}
The code can be compiled with both VC6.0 and VC2010.
But I have questions as blow:
const int *p = &i1;
It means what the "p" points can not be modified,but p can not be modified,am I right?
so
p = &i2;
this line can be complied,yes?
This line:
int const *p2 = &i1;
In my mind,this means p2 can not be modified while what p2 points can be changed, am i right?
Why the
p2 = &i2;
can be compiled?
About this line:
const int const *p3 = &i1;
p3 = &i2;
Oh,god... I am crazy. I have no idea why this line can be compiled with no error...
Can any body help me?
Another code which confused me is here:
class Coo2
{
public:
Coo2() : p(new int(0)) {}
~Coo2() {delete p;}
int const * getP() const
{
*p = 1;
return this->p;
}
private:
int* p;
};
why this code can be compiled?
In
int const * getP() const
I have change the value or *p !
Here we consider 4 types of pointers declarations:
int * w;
It means that w is a pointer to an integer type value. We can modify both the pointer and its content. If we initialize w while declaration as below:
int * w = &a;
Then, both of below operations are viable:
w = &b;(true)
*w = 1;(true)
int * const x;
It means x is a constant pointer that points to an integer type value. If we initialize x while declaration as below:
int * const x = &a;
Then, we cannot do: x = &b;(wrong) because x is a constant pointer and cannot be modified.
However, it is possible to do: *x = 1;(true), because the content of x is not constant.
int const * y; //both mean the same
const int * y;
It means that y is a pointer that points to a constant integer value. If we initialize y while declaration as below:
int const * y = &a;
Then, it is possible to do: y=&b;(true) because y is a non-constant pointer that can point to anywhere.
However, we cannot do: *y=1;(wrong) because the variable that y points to is a constant variable and cannot be modified.
int const * const z; //both mean the same
const int * const z;
It means that z is a constant pointer that points to a constant integer value. If we initialize z while declaration as below:
int const * const z = &a;
Therefore, non of below operations are viable:
z = &b;(wrong)
*z = 1;(wrong)
With the help of pointer, you can actually do two things.
You can change the data it is pointing to but cannot point to a different memory location.
You can point it to a different memory location but cannot change the data it is pointing to.
Now, when you say, int const* ptr or int const* ptr, it falls under first category. It's same as -
const int num = 5; // Both mean the same.
int const num = 5;
To, actually not able to change to a different location, i.e., pointer to a constant location but be able to modify the data, the semantics should be int* const. Since the content of the pointer is a constant, it should be initialized while declaration.
int num = 5;
int* const ptr; // Wrong
ptr = # // Wrong
int* const ptr = #
*ptr = 100;
However, there is a third kind. Constant pointer to a constant location, which can neither point to a different memory location nor change the data it is pointing to. ( i.e., const int* const )
And now answering the questions, the first two can be compiled because they are not pointing to constant locations. So, they can be modified at later stages too.
const int const *p3 = &i1;
p3 = &i2; // Wrong
In the above snippet, p3 is a constant pointer to a constant location. So, it cannot be modified.
const at the end of a member function says it is not going to change the state of the object. When you say *p = 1;, you are not changing the state of the object. p still points to the same memory location. This is not allowed to do -
int const * Coo2::getP() const
{
*p = 1; // State of `p` is still not modified.
p = new int ; // Error: Changing the memory location to which p points.
// This is what changing the state of object mean and
// is not allowed because of `const` keyword at the end of function
return this->p;
}
Hope, now you understand why the program compiles :)
int const * p; and const int * p are the same. It is when the const comes after the * that
the semantics of the expression change.
I know, it's crazy.
const int *p = &i1;
int const *p2 = &i1;
These both declare non-const pointers to const data.
That is, using p, you cannot change the data it points to. However, you can change the pointer itself, for example, by assigning as p = &i2 which is legal. But *p = 87987 is illegal, as the data p points to is const!
--
int * const p = &i1;
This declares const pointer to non-const data. That is, p=&i2 is illegal, but *p = 98789 is legal.
--
const int * const p = &i1;
This declares const pointer to const data. That is, now both p=&i2 and *p=87897 are illegal.
The two are exactly the same. What matters is the position of the qualifier relative to the asterisk (*):
int const *p; // normal pointer to const int
const int *p; // ditto
int *const p; // const pointer to normal int (rarely useful)
int const * const p; // const pointer to const int
Here is a pointer to a constant:
const int* p;
The following statement is illegal, because it attempts to change the
value of a constant:
*p = 3;
But this one is legal, because the pointer itself is not a constant:
p = &x;
On the other hand, this declaration shows a constant pointer to a variable.
int* const p;
In that case, the following statement is legal, as the variable can be changed:
*p = 3;
but this one is not, because it attempts to change the value of a constant.
p = &x;
Reference link:http://faculty.cs.niu.edu/~freedman/241/const-ptrs.txt
No, the const keyword before the * means that the variable you are pointing to is a "const" variable and only it can not be modified.
If you want a pointer that can't be reassigned then you need to declare it as Foo* const p = &bar;
If you want a pointer that points to a "const" object that can't be reassigned declare it as const Foo* const p = &bar
It is perfectly fine to have a pointer of const int* foo be assigned to a pointer of const int* const bar just like it is fine to have an int's value assigned to a const int. Think of it in the same manner.
int const * is the same as const int *
Succinctly; each combination of read/write int & pointer;
int main() {
int a,b;
int* w; // read/write int, read/write pointer
w= &b; // good
*w= 1; // good
int* const x = &a; // read only pointer, read/write int
// x = &b; // compilation error
*x = 0; // good
int const * y; // read/write ptr, read only int
const int * y2; // " " "
y = &a; // good
// *y = 0; // compilation error
y2 = &a; // good
// *y2 = 0; // compilation error
int const * const z = &a; // read only ptr and read only int
const int * const z2 = &b; // " " " "
// *z = 0; // compilation error
// z = &a; // compilation error
// *z2 = 0; // compilation error
// z2 = &a; // compilation error
}