Sign in to follow this  

quick explanation of references please

This topic is 4691 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In the following block of code can anyone explain why the sizeof() function returns a 4. And what are the differences in array declarations between b and c.
A little demonstration:
#include <iostream>
using namespace std;
int main(void) {
        int a;
        int b[10];
        int *c = new int[10];
        cout << sizeof(int) << " = " << sizeof(a) << endl;	// 4
        cout << sizeof(int[10]) << " = " << sizeof(b) << endl;	// 40
        cout << sizeof(int*) << " = " << sizeof(c) << endl;	// 4
	delete [] c;

Share this post


Link to post
Share on other sites
sizeof() returns the size of 'something' in bytes (as it is known at compile time).

An int on your computer is 4 bytes (32 bits).
A pointer (int *, void *, etc.) is also 4 bytes (32 bits).

An array of 10 ints, is thus 40 bytes. A pointer to this array is only 4 bytes.

Try using 'char' instead of 'int' to see what happens.

Compiling and running the same program on an old 8bit homecomputer would give you different results, something like: 2, 20, 2.

Hope that helps! :)


Edit: added some extra information.

Share this post


Link to post
Share on other sites
sizeof() returns the size in bytes of the datatype passed to it. In this case an int, which is 4 bytes (or 32 bits) on your computer.

The difference between b and c is that b is allocated on the stack, while c is being allocated on the heap using new. In order to use memory allocated on the heap (=)), you need to obtain a pointer to the beginning of the block allocated by new.

edit: too slow!

Share this post


Link to post
Share on other sites
You might be confused by the fact that you can almost always use the same notation on both pointers and arrays. Like, you can use brackets on a pointer:

int *a = new int[10];
a[1] = 2;

or you can do pointer arithmetic on an array reference:

int b[10];
*(b + 1) = 2;

So you might be tempted to think that they are the same thing. But despite their incredible similarities, pointers and array references are not the same. Your sizeof() code is a great example of where they differ.

Share this post


Link to post
Share on other sites
@ontheheap:

The heap nor the stack have anything to do with sizeof(). It's like pinacolada said: the array and the pointer are different things (no matter where they're allocated).

I personally see an array as a pointer known at compile-time. Pointers which can only be resolved at run-time often need some space in RAM. That's where the sizeof() confusion comes from.

To put it simple:

'int *' is a place to _store_ a pointer [to an array or some other place in memory]. Its size is 4 bytes on most modern computers.


'[', '*', '&' and ']' are your friends! :)

[Edited by - Jan-Lieuwe on February 9, 2005 4:14:51 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Jan-Lieuwe
@ontheheap:

The heap nor the stack have anything to do with sizeof(). It's like pinacolada said: the array and the pointer are different things (no matter where they're allocated).


The OP stated two questions, the first being the sizeof() question, the second being "differences in array declarations between b and c". The difference in b and c helps explain why their sizeof()'s are different results.

Share this post


Link to post
Share on other sites
references are EXACTLY like pointers, except that U CANT have NULL references
(for some functions using references can provide speed improvements cuz u dont have to validate a pointer)

Share this post


Link to post
Share on other sites
Java doesn't have pointers (from my point of view) because of security reasons. Just imagine a pointer intentionally pointing to an unsafe área could bring down not only your app, but the entire JVM.

Plus, I see Java like "C++ without all that things that make programmers run away from it". so to make things simpler, they used only references.

Check this. (point 17).

And read this. A curious discussion about references.

Hope this helps you to understand things a little more.
If you really want to understand all about pointers, just ignore java. When you feel a little more confident about them, Java references will seem pretty simple and logical.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jan-Lieuwe
@ontheheap:

The heap nor the stack have anything to do with sizeof(). It's like pinacolada said: the array and the pointer are different things (no matter where they're allocated).


I always appreciate people checking replies for inaccuracies, but in this case I was answering two separate questions. One regarding sizeof(), and the other regarding the difference between using and not using new to create an array.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kommi10
are there still advantages of using pointers ove references?


Once set, you cannot change what a reference refers to. It really is "another name" for a given variable.


int i;
int& j = i; // j is an alias for i.


If you need to be able to change what you're referring to, you need a pointer.

Quote:
I know Java only has references which makes programming alot easier in that language.


Java references are a very different kind of beast: so long as you have an accessible reference, the object is kept alive. C++ references do not affect object lifetimes (neither do pointers). If the object dies, you will have a dangling reference. Likewise, you can't cause an object to be destroyed by simply setting pointers to NULL (references cannot be reassigned, remember? [smile])

You may want to look at smart pointers though.

Share this post


Link to post
Share on other sites
Basic difference between an array and a pointer: with an array, the array itself (the block of memory) is the "variable". Its address is implicitely known to the program - either because it is in a fixed location (a static array variable), or because its location is known in relation to the top of the stack (a local array variable). The array's size is also known, because it is part of its type declaration. So, when you directly refer to the array, either as array, or array[index], the compiler can automatically substitute the proper address (treated as an address, or as the location for an array element, depending on what you're doing with it).

A pointer, on the other hand is a variable which holds the address of another variable. The address of the pointer is also known, in the same terms as the address of an array as mentionned above (and in fact, in the same terms as any other variable). But the address of the pointed variable is only known through the pointer variable itself. i.e. the compiler must look up what's actually stored at the (known) memory location of the pointer variable, and then use that to find what was pointed to.

Now, you'll have heard that arrays "decay" to pointers. Why is that so? Because even though the compiler knows the address of the array without needing to store it in a variable, once you, the programmer, has fetched the array's address in order to, for example, pass it to a function, what you have is an actual variable containing the address of the array - how else do you expect to be able to pass it to a function? The alternative would have been to have an entire function for each possible array (address) you'd pass to it, and to pick one or the other depending on what array you've chosen (as a side note, it is possible to achieve that result using non-type template parameters). So now, you have a variable containing an address... SURPRISE! that's what a pointer is!
In the conversion, you have lost some information (which is why the term decay is used), namely the size of the array. That is, how many elements you are really pointing to. That's a language design decision. C could just as well had enforced that you must specify how many elements you are pointing to in the actual type of the pointer (as Pascal does, if I remember correctly), but that would have prevented you from passing differently-sized arrays to a function, for if the size of the array were part of the parameter type, you'd get a type mismatch (Pascal is annoying). Given how loose the typing rules are in C (and they were even more so -practically inexistant- in earlier versions of the language) that would have been a huge wart on the language.

Finally, references, in C++, are treated in two different ways:
First, if what the reference refers to is known at compile-time, such as the example I gave in my previous post: int i; int& j = i;, the compiler can just refer to the original variable and ignore the existence of the reference.

Granted, that's just an optimization, but the idea is worth keeping in mind when you are trying to figure out what references are meant to be - they aren't intended to be separate variables, but really just another name for an exisiting variable. Thus, references are particularly handy to reduce typing when you would have to do a sequence of member accesses: int& i = foo.bar.baz[25].quux[3].x;

Otherwise, it is simply treated as an implicitely dereferenced pointer to whatever variable you passed. That's what happens when a function takes a reference parameter (or does return a reference). Additional trickery is done with const references, allowing you to pass literals (such as 42 or 666) - a temporary variable is actually created, the address of which is passed to the function. Some more type trickery is done with function template parameters (notably, if a function expects a reference, array decay will not happen: if you do template <class T> foo(T&); int bar[10]; foo(bar);, then T will be int [10], and not int*).
There are some slightly less clear cases, such as creating a reference to the result of a function: int& i = foo(), as it depends on things like the presence of inlining and so on...

Conclusion:

  • If you're passing an array, use a pointer. Since arrays decay to pointers, and (non-void) pointers can be indexed as arrays, it is essentially equivalent to passing by reference to the array (indeed, taking a reference to an array is a no-op; compilers may warn you about that).
    Or better, forgo arrays, and use a C++ std::vector.
  • If you need to be able to change what variable you're refering to, use a pointer.
  • To make an alias to another variable, create a reference to it.
  • If you don't need to modify the original object, pass a const reference to your function, unless the variable is of a basic type (e.g. int), in which case you can just pass by value.
  • If you need to modify the original object, pass by reference.
  • If you really need to make a local copy, either pass by const reference and create a local variable, or pass by value. Your call. Different compilers may produce different code for either.

Share this post


Link to post
Share on other sites
On the topic of Java, I find it makes way more sense to think of Java's "references" as being the same thing as C++'s "pointers".

The defining features of C++'s "references" are that: 1) they can't be reseated, and 2) they can sometimes resolve to just be an alias (see Fruny's post). But neither of these facts are true for Java's "references". So if I were to say "Java references are like C++ references, except Java references can be reseated and they don't become aliases", then that would be similar to me saying, "My pet is like an elephant, except instead of being huge with a thick hide, he's small and furry and he barks."

Share this post


Link to post
Share on other sites

This topic is 4691 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this