What is the difference? Because this:
int Value = 50;
int *pValue = &Value;
*pValue = 88;
and ref version do the same:
int Value = 50;
int &rValue = Value;
rValue = 88;
Which one is better to use? Thanks.
In this case, they are equivalent.
It does not matter which you use, and neither is "best".
If you really want to choose between them then the reference is probably more idiomatic. I generally stick to references wherever I can because my OCD likes it: they feel "tighter", cannot be re-bound (with or without you noticing) and don't require a dereference to get to the value.
But I'm not aware of any general consensus on the issue for cases such as this.
Also note that the two may not compile to the same code if your implementation does not implement references with pointers, though I know of no implementation like that, and you wouldn't notice the difference anyway.
A pointer is the address of the memory location. You can change the value of that address to point at different memory addresses.
A reference is an alias of the variable. You can only assign this alias during declaration. You cannot change which variable the reference is an alias of after it's declared.
The following pointer assignments are not possible with references.
int a = 10;
int b = 20;
int* pInt = NULL; // A pointer pointing at nothing.
pInt = &a; // pInt now points at a
pInt = &b; // pInt now points at b
As for which one is better, it all depends on context.
I use references for method and function parameters.
void updateFoo(Foo& foo)
I use references to alias complex objects.
Foo& foo = bar.getBaz().getFoo(); // easy access to foo
I use pointers for dynamically allocated objects.
Foo* pFoo = new Foo();
I use pointers for things which may point at different values (including no value at all).
Foo* pFoo = NULL;
if (condition1)
pFoo = &foo1;
else (condition2)
pFoo = &foo2;
As a general rule, I default to references and use pointers in places where the limitations on references cause problems.
The differences are:
Reference is an alias of an object and has the same address as the object.
int a; // address of a : 0x0012AB
int &ref = a; // address of ref : 0x0012AB (the same)
References must be initialized :
int &ref = a; // GOOD, is compiling
int &ref; // BAd, is not compiling
Pointer is another variable that holds an address:
int a = 5; // address of a : 0x0012AB
int *p = &a; // address of p : 0x0012AF (is different )
// value of a is 5
// value of p is 0x0012AB (address of a)
Pointers can be NULL
int *p = NULL;
My rule of thumb is to favor using a reference or const reference, unless a pointer is required.
The reference may not be reseated, and it is syntactically cleaner. The reference also guarantees to you that the reference is not NULL.
I may also use a pointer for convenience when using arrays.
I agree with justin's answer and would like to clarify it with the tiniest example.
Suppose you don't quite remember the syntax of a 2D image geometric library: is it
bool BooleanOr( const Bitmap & input1, const Bitmap & input2, Bitmap * output );
or is it
bool BooleanOr( Bitmap * output, const Bitmap & input1, const Bitmap & input2 );
If in your company everybody uses pointers for outputs and const references for inputs it's virtually impossible to make a mistake: when you see calls such as
BooleanOr( thisBitmap, thatBitmap, & anotherBitmap );
you immediately know the syntax.
Great answers here. I would like to point out 2 specific usages of references:-
Case 1: While implementing operator[]. This operator typically needs to return something that can be used as the target of an assignment Example:-
vector<int> v(20);
v[1] = 5; //The target of the assignment is the return value of operator []
Here the operator [] returns a reference of the element at the specified index in the vector. Had operator [] been designed to return a pointer to the element at the specified index the 2nd line would have to be written like this:-
*v[1] = 5
Now that makes v look like it's a vector of pointers - which it's definitely not!! Thus for sanity to prevail - the operator [] returns a reference and not a pointer to the indexed element in the vector
Case 2: No explicit null check required for references. Some answers have already talked about it - wanted to present the advantage using a code snippet:-
void fun(const int& val)
{
cout << val;
}
void fun(const int* val)
{
if (val){ //Additional overhead with pointers
cout << *val;
}
}
Related
My background is in more managed languages (C#, python) but I am becoming more experienced in C/C++. I am familiar with why the selection by reference (.) and selection through pointer operation (->) operators are different. In all cases I have encountered, if you use the incorrect one, it will result in a compile error. If that is the case, they why were they not made into one operator? Is there a case where using either on the same object results in different, meaningful and useful results?
This question inspired by this answer:
Is this right way to call a function in c++?
In C++ you can overload the ->-operator, which is used in pretty much all smart pointer implementations. However, some of those also have their own methods, i.e. to release a reference.
struct test {
int x;
};
std::shared_ptr<int> ptr(new test);
// Write to member x of the allocated object
ptr->x = 3;
// Reset the shared pointer to point to a different object.
// If there are no further shared_ptrs pointing to the previously allocated one,
// it is deleted.
ptr.reset(new test)
Additionally, it would be quite messy for the compiler to resolve operator-. for something like multiple-level pointers, i.e. test*** ptr. With your logic, ptr.x, (*ptr).x, (**ptr).x and (***ptr).x would all be the same.
You cannot apply -> to a reference to a basic type and you cannot apply . to a pointer, but you can apply both to a user-defined type and they will have different meanings. The simplest example is a smart pointer, like std::shared_ptr:
struct A { int x; };
std::shared_ptr<A> p(new A);
p->x = 10;
p.reset();
Is there a case where element selection by reference and element selection through pointer operation are both valid?
Since you can overload operator->() in C++, you can actually arrive at situations where you can use -> and . interchangeably on the same object. You can even engineer things so that you get a different result, as per this example:
#include <iostream>
struct Bar
{
void hello() const { std::cout << "Bar!!!\n"; }
};
struct FooBar
{
Bar bar;
void hello() const { std::cout << "FooBar!!!\n"; }
const Bar* operator->() const {return &bar; }
};
int main()
{
FooBar fb;
fb->hello();
fb.hello();
}
Of course, in real code you would never do something as crazy as this (although I have seen this kind of thing in "production" code).
the short answer would be a smart pointer
you can access the smart pointer class arguments using the "." (if you make your own smart pointer class you can extract from there for instance the current reference count) while you would use the "->" operator to access whatever is being stored using the smart pointer.
I have some confusion about the shared_ptr copy constructor. Please consider the following 2 lines:
It is a "constant" reference to a shared_ptr object, that is passed to the copy constructor so that another shared_ptr object is initialized.
The copy constructor is supposed to also increment a member data - "reference counter" - which is also shared among all shared_ptr objects, due to the fact that it is a reference/pointer to some integer telling each shared_ptr object how many of them are still alive.
But, if the copy constructor attempts to increment the reference counting member data, does it not "hit" the const-ness of the shared_ptr passed by reference? Or, does the copy constructor internally use the const_cast operator to temporarily remove the const-ness of the argument?
The phenomenon you're experiencing is not special to the shared pointer. Here's a typical primeval example:
struct Foo
{
int * p;
Foo() : p(new int(1)) { }
};
void f(Foo const & x) // <-- const...?!?
{
*x.p = 12; // ...but this is fine!
}
It is true that x.p has type int * const inside f, but it is not an int const * const! In other words, you cannot change x.p, but you can change *x.p.
This is essentially what's going on in the shared pointer copy constructor (where *p takes the role of the reference counter).
Although the other answers are correct, it may not be immediately apparent how they apply. What we have is something like this:
template <class T>
struct shared_ptr_internal {
T *data;
size_t refs;
};
template <class T>
class shared_ptr {
shared_ptr_internal<T> *ptr;
public:
shared_ptr(shared_ptr const &p) {
ptr = p->ptr;
++(ptr->refs);
}
// ...
};
The important point here is that the shared_ptr just contains a pointer to the structure that contains the reference count. The fact that the shared_ptr itself is const doesn't affect the object it points at (what I've called shared_ptr_internal). As such, even when/if the shared_ptr itself is const, manipulating the reference count isn't a problem (and doesn't require a const_cast or mutable either).
I should probably add that in reality, you'd probably structure the code a bit differently than this -- in particular, you'd normally put more (all?) of the code to manipulate the reference count into the shared_ptr_internal (or whatever you decide to call it) itself, instead of messing with those in the parent shared_ptr class.
You'll also typically support weak_ptrs. To do this, you have a second reference count for the number of weak_ptrs that point to the same shared_ptr_internal object. You destroy the final pointee object when the shared_ptr reference count goes to 0, but only destroy the shared_ptr_internal object when both the shared_ptr and weak_ptr reference counts go to 0.
It uses an internal pointer which doesn't inherit the contests of the argument, like:
(*const_ref.member)++;
Is valid.
the pointer is constant, but not the value pointed to.
Wow, what an eye opener this has all been! Thanks to everyone that I have been able to pin down the source of confusion to the fact that I always assumed the following ("a" contains the address of "b") were all equivalent.
int const *a = &b; // option1
const int *a = &b; // option2
int * const a = &b; // option3
But I was wrong! Only the first two options are equivalent. The third is totally different.
With option1 or option2, "a" can point to anything it wants but cannot change the contents of what it points to.
With option3, once decided what "a" points to, it cannot point to anything else. But it is free to change the contents of what it is pointing to. So, it makes sense that shared_ptr uses option3.
What is the difference in the following code:-
int a;
int *p;
p=&a;
function(p);
and
int a;
function(&a);
I was reading a book where sometimes they have used the first code and sometimes the other. Its not a good book though (by a local author).
Will both codes work the same way or is there any difference?
Also is there any difference in terms of efficiency and does it matter that much?
Thanks
For a reference, the object must be already existing in order to reference it. As for a pointer, the object does not need to be already existing when declaring a pointer
Example:
int &i = 10; //Invalid
const int &i = 10; //Valid
also
you cannot declare an array of references:
int &tab[] = {2,3}; //Invalid
int * tab[] = {2,3}; //Valid
In practice, reference are mostly used as functions parameters and return values;
As far as I know compiler implements references as pointers. So there should be no difference in performance. But references are more strict and can protect you from making mistakes. For example you can't rebind references or can't perform arithmetic with them
Also some people prefere to pass pointers to the function that modify object. For example
void changeVal(int *p)
{
*p = 10;
}
They say it's more readable when you see:
changeVal(&var)
than
changeVal(var);
EDIT
You can think of reference as another name of the object it refers to. So all the changes made to reference are applied to the object. Here is an example:
void foo_copy(int a) //pass by copy
{
a = 10; //changes copy
}
void foo(int &a) //bass by reference
{
a = 10; //changes passed value
}
void foo(int *a) //pass an adress of a
{
(*a) = 10; //change a value pointed by a
a = nullptr; //change a (the pointer). value is not affected
}
In above two approaches, Both are using pointers, there is no difference except memory equal to sizeof(int *) will be allocated on stack for "int *p".
In case of call by reference, Refer. It seems you are beginner and learning things, you will come to know more about passing by reference and its use more while using copy constructor in classes.
The two code snippets should be equivalent when compiled with a modern compiler. The extra declaration and assignment (p=&a;) is optimised away.
I am looking over some open source code and they listed some strange instance in a class defined as:
Obj *&obj;
I had no idea that was possible! What does that mean or even do? The pointer and reference symbols should counteract in my opinion. But maybe it does something special I do not know about?
Looking in the code, they use it as if the instance was a pointer. ie: obj->method(). So then why did they include the &?
That is reference to a pointer. Think in this way:
A *pa = new A(); //pa is pointer to A
A * & rpa = pa; //rpa is reference to pa
rpa = nullptr; //it modifies pa as well
if ( pa == nullptr )
{
std::cout << "pa is nullptr" << std::endl;
}
It will print "pa is nullptr" on the console.
If you find A * & difficult to read, then you can use typedef as:
typedef A* PA;
PA & rpa = pa; //same as before
The code like you wrote it won't compile, since it declares a reference to a pointer, but the reference is uninitialized. For example, the following code won't compile:
string *&s;
(unless it's a member in a class), but this will:
string *p;
string *&s = p;
Another possibility, is that this is just a typo and they meant to write Obj *obj; ;)
That's a reference to a pointer. After all, a pointer is also a value. You might use it to reassign a pointer held by the caller. To illustrate:
bool allocate(t_object*& p) {
assert(0 == p);
p = new t_object;
...
}
Then:
t_object* obj(0);
if (!allocate(obj)) {...}
// obj now points to something
Some people find it easier to manage/read that its most direct alternative (bool allocate(t_object** p)).
As to why a reference to a pointer was chosen in the program -- there's not enough context, but you can ask yourself if the program would be better if the member were declared t_object** const?
It's a reference to a pointer. A pointer is a data-type, why shouldn't you be allowed to have references to one?
It means the same thing as any other type reference - it's an alias for a pointer.
What does const really mean? Read-only seems to encapsulate its meaning for me, but, I'm not sure I'm right.
If read-only and const are different, could someone tell me why?
What prompted this question was this answer where he states const "just" means read-only in C. I thought that's all const meant, regardless of whether it was C or C++. What does he mean?
For an answer to the specific differences in const in C vs C++, I've created a new question: How does "const" differ in C and C++? as per R..'s suggestion.
By declaring a variable as const you indicate compiler that you have no intentions of modifying that variable. But it does not mean others don't have! It's just to allow some optimization and to be notified by a compile error (note, that it's mostly compile error, while const == ReadOnly would mean runtime errors).
const does not mean read only, because you can write const volatile, that would mean it could change by itself anytime, but I have no intentions to modify it.
EDIT: here is a classical example: consider I'm writing the code that reads current time from a memory-mapped port. Consider that RTC is mapped to memory DWORD 0x1234.
const volatile DWORD* now = (DWORD*)0x1234;
It's const because it's a read-only port, and it's volatile because each time I will read it it will change.
Also note that many architectures effectively make global variables declared as const read-only because it's UB to modify them. In these cases UB will manifest itself as a runtime-error. In other cases it would be a real UB :)
Here is a good reading: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
The compiler won't allow something declared as const to be modified. It is as you say.
It's mostly used in function prototypes to inform the user that a function won't touch this or that when passed pointers. It also works as kind of failsafe for yourself.
A lot of people are telling you that const means you can't modify it. That is patently false. const can trivially be cast away. Note this snippet:
void foo(const int *somevalue)
{
int *p = (int*) somevalue;
*p = 256; // OMG I AM EVIL!!!!11
}
Your compiler will not stop you from doing this. So, what then is the purpose of const? I'd call it more of a suggestion. It reminds you as you look at function prototypes of the contract that your functions expect. Your compiler will yell at you if you carelessly break it. (But not if you intentionally break it, as with the above cast.)
In some cases the standard intentionally breaks const. Note the return values of strstr for example: by definition it will return some offset into the const buffer you provide it... But the returned value is not const. Why? Well, this would break meaningfully using the return value of strstr on a non-const buffer.
Two byte for byte identical (except for the comments) minimal case examples...
First in C, gcc will emit a warning...
/* Function taking a pointer to an array of
two read only integers.*/
void a( const int (* parray)[2]);
void b(void)
{
int array[2] = {1,2};
const int crray[2] = {1,2};
/* C reserves the right to stash this in a read-only location.*/
a( &array);
/* warning: passing argument 1 of ‘a’ from incompatible pointer type*/
a( &crray); /* OK!*/
}
Now the same thing in C++... g++ is quite happy with it.
// Function taking a pointer to an array
// of two integers which it promises not to modify.
// (Unless we cast away it's constness ;-P)
void a( const int (* parray)[2]);
void b(void)
{
int array[2] = {1,2};
const int crray[2] = {1,2};
a( &array); // C++ has no problem with this.
a( &crray); // OK!
}
const char * hello_1{ "Hello!" };
const char hello_2[]{ "Hello!" };
char * ptr{};
// take away the const-nes
// ptr = (char *)hello_1;
// *ptr = '*'; <-- write access violation
// hello_1 is in a read only memory
// take away the const-nes
ptr = (char *)hello_2;
*ptr = '*'; // <-- OK
// hello_2 is modifiable
Pointers point to memory, and char * points to memory in the data segment which is read only. The difference between char * and char [] is that while both are declared the same way on the data segment, char [] is treated as readable because it is pushed onto the stack if it is used.
C++ allows for the definition of const member functions. const member functions are the only functions that be called on const objects. Also, const member functions cannot modify any data members of a class (unless the data member marked mutable).
class Foo
{
int data;
void Bar();
void ConstBar() const;
};
void Foo::ConstBar() const
{
// Error! cannot modify i as ConstBar is a const member function.
// i = 0;
}
// Usage:
const Foo foo_instance;
// Error! cannot call non-const member on a const object.
// foo_instance.Bar();
// OK
foo_instance.ConstBar();
Const means that a pointer or reference cannot be used for a write or read-modify-write operation without casting away const. It does NOT mean what the C++ standard tries to claim it means (the C++ standard is just wrong on this).
A variable defined like this:
/* auto */ int const x = 1;
is patently NOT read-only since otherwise it could not be initialised. Rather, the kind of variable x is "reference const to int" (and NOT reference to const int) or alternatively lvalue const of int. Note carefully the "const" is associated with a pointer or reference it has nothing to do with the storage, nor the type of the value residing in that storage.
This is rather unfortunate because the contract provided by const is extremely weak, and in particular fails to allow caching of a pointed at or referred to memory location, precisely because it does NOT mean immutable storage.
The bottom line is: const is an access modifier associated with a symbolic reference or pointer which is used by the programmer to allow the symbol provider to establish an obligation on the symbol client, or for the symbol client to promise the symbol provider it does not modify storage via this symbol (for example a function accepting a pointer const to int promises not to modify the pointed at int).
This has nothing to do with variables:
int const *p = (int*)malloc(sizeof(int));
and clearly little to do with storage (malloc'ed store is always writable).
Instead you should think of const as a way of communicating invariants, obligations or requirements between parts of the program, put in place by the programmer for the programmers purposes, and propagated by the type system. Unfortunately the type system isn't sound and fails to properly propagate constness correctly:
X *last;
struct X { int a; X() : a(0) { last=this; } };
X const x; // x is const?
last->a = 1; //really ??
IMHO the only opportunity a compiler has to make store immutable is for actual constants such as string literals (maybe) or static (global) storage. Automatic, heap, and temporary storage cannot be made read-only in practice.