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.
Related
so i'm learning c++ and i just learned about dynamically allocated memory for class. there's something that make me it feel weird.
int main()
{
person* pOne = new person("mike", 35);
cout << pOne << " " << pOne->getName() << endl;
person pTwo = { "dave", 30 };
cout << pTwo.getName() << endl;
return 0;
}
i think that when we want to call getName() function in pOne, we should do it like *pOne->getName() because pOne hold the memory location, not the person object itself. but if i do that i'll got compiler error.
i do it with pTwo that not dynamically allocated and it work like i tought.
so, can someone explain the logic of not using "*" when trying to call function?
The built-in operator a->b is defined as (*a).b, so the dereference is "hidden" inside the -> operator.
-> is just a syntactic sugar: a->foo is the same as (*a).foo. So when you use -> you in fact dereference the pointer.
i do it with pTwo that not dynamically allocated and it work like i tought.
so, can someone explain the logic of not using "*" when trying to call function?
You mixed different concepts, it is not related how you allocated memory, but on which type of variable you access member:
struct Foo { void bar(); };
Foo f; // type of f is Foo
f.bar(); // access on type Foo is through .
Foo *pf = &f; // type of pf is Foo*
pf->bar(); // derefence and access on type Foo* is through ->
(*pf).bar(); // the same as above and since type of *pf is Foo we can use .
(&f)->bar(); // type of &f is Foo*, so we can use ->
(*(&f)).bar(); // crazy stuff
It'll be clearer if you change the way you write your code.
Instead of:
person *pOne = new person("mike", 35);
Write:
person* pOne = new person("mike", 35);
This means the same to the compiler, but makes it clearer to humans that this is a person* (a pointer-to-person) called pOne.
Now it makes more sense that you still perform pointer operations on pOne, not on *pOne.
The older, right-aligned asterisks approach comes from the C world, in which people wanted you to think of it more like "there is a person at *pOne". And, in your case, that is true: (*pOne).getName() would also have worked. However, that looks pretty ugly to me, and *pOne isn't always an actual person — it depends on what (if anything) the pointer is set to.
The key point here is that -> (as in pOne->getName()) does that dereferencing for you. Writing (*pOne)->getName() would be doing it twice.
Your final example of pTwo.getName() is just a bog-standard object access.
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;
}
}
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.
I've mostly only worked with C and am running into some unfamiliar issues in C++.
Let's say that I have some function like this in C, which would be very typical:
int some_c_function(const char* var)
{
if (var == NULL) {
/* Exit early so we don't dereference a null pointer */
}
/* The rest of the code */
}
And let's say that I'm trying to write a similar function in C++:
int some_cpp_function(const some_object& str)
{
if (str == NULL) // This doesn't compile, probably because some_object doesn't overload the == operator
if (&str == NULL) // This compiles, but it doesn't work, and does this even mean anything?
}
Basically, all I'm trying to do is to prevent the program from crashing when some_cpp_function() is called with NULL.
What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the == operator)?
Is this even the right approach? That is, should I not write functions that take an object as an argument, but rather, write member functions? (but even if so, please answer the original question)
Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?
Basically, all I'm trying to do is to
prevent the program from crashing when
some_cpp_function() is called with
NULL.
It is not possible to call the function with NULL. One of the purpose of having the reference, it will point to some object always as you have to initialize it when defining it. Do not think reference as a fancy pointer, think of it as an alias name for the object itself. Then this type of confusion will not arise.
A reference can not be NULL. The interface makes you pass a real object into the function.
So there is no need to test for NULL. This is one of the reasons that references were introduced into C++.
Note you can still write a function that takes a pointer. In this situation you still need to test for NULL. If the value is NULL then you return early just like in C. Note: You should not be using exceptions when a pointer is NULL. If a parameter should never be NULL then you create an interface that uses a reference.
A C++ reference is not a pointer nor a Java/C# style reference and cannot be NULL. They behave as if they were an alias to another existing object.
In some cases, if there are bugs in your code, you might get a reference into an already dead or non-existent object, but the best thing you can do is hope that the program dies soon enough to be able to debug what happened and why your program got corrupted.
That is, I have seen code checking for 'null references' doing something like: if ( &reference == 0 ), but the standard is clear that there cannot be null references in a well-formed program. If a reference is bound to a null object the program is ill-formed and should be corrected. If you need optional values, use pointers (or some higher level construct like boost::optional), not references.
As everyone said, references can't be null. That is because, a reference refers to an object. In your code:
// this compiles, but doesn't work, and does this even mean anything?
if (&str == NULL)
you are taking the address of the object str. By definition, str exists, so it has an address. So, it cannot be NULL. So, syntactically, the above is correct, but logically, the if condition is always going to be false.
About your questions: it depends upon what you want to do. Do you want the function to be able to modify the argument? If yes, pass a reference. If not, don't (or pass reference to const). See this C++ FAQ for some good details.
In general, in C++, passing by reference is preferred by most people over passing a pointer. One of the reasons is exactly what you discovered: a reference can't be NULL, thus avoiding you the headache of checking for it in the function.
You can use a special designated object as the null object in case of references as follows:
class SomeClass {
public:
int operator==(SomeClass &object) {
return (this == &object);
}
static SomeClass NullObject;
};
SomeClass SomeClass::NullObject;
void print(SomeClass &val) {
if(val == SomeClass::NullObject)
printf("\nNULL");
else
printf("\nNOT NULL");
}
You should use NULL only with pointers. Your function accepts a reference and they can't be NULL.
Write your function just like you would write it in C.
C++ references naturally can't be null, you don't need the check. The function can only be called by passing a reference to an existing object.
What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the == operator)?
Is this even the right approach? ie. should I not write functions that take an object as an argument, but rather, write member functions? (But even if so, please answer the original question.)
No, references cannot be null (unless Undefined Behavior has already happened, in which case all bets are already off). Whether you should write a method or non-method depends on other factors.
Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?
If you need to represent "no object", then pass a pointer to the function, and let that pointer be NULL:
int silly_sum(int const* pa=0, int const* pb=0, int const* pc=0) {
/* Take up to three ints and return the sum of any supplied values.
Pass null pointers for "not supplied".
This is NOT an example of good code.
*/
if (!pa && (pb || pc)) return silly_sum(pb, pc);
if (!pb && pc) return silly_sum(pa, pc);
if (pc) return silly_sum(pa, pb) + *pc;
if (pa && pb) return *pa + *pb;
if (pa) return *pa;
if (pb) return *pb;
return 0;
}
int main() {
int a = 1, b = 2, c = 3;
cout << silly_sum(&a, &b, &c) << '\n';
cout << silly_sum(&a, &b) << '\n';
cout << silly_sum(&a) << '\n';
cout << silly_sum(0, &b, &c) << '\n';
cout << silly_sum(&a, 0, &c) << '\n';
cout << silly_sum(0, 0, &c) << '\n';
return 0;
}
If "no object" never needs to be represented, then references work fine. In fact, operator overloads are much simpler because they take overloads.
You can use something like boost::optional.