slick
slick

Reputation: 65

How is a reference and a pointer to an array different from each other and which one is preferable?

I am a cpp beginner and have been experimenting with come very basics. I was exploring how are reference and pointer different from each other in regards to arrays and wrote a simple snippet.


int main() {
    //char *  c2 = "C";
  //std::cout << &c2<<std::endl;
    //std::cout << *c2<<std::endl;
    int arr[]={21,2,3,4,5,6,7,8,9,10};
    int (&ar)[10]=arr;
    int *ar1=arr;
    std::cout<<"add of arr[0] :"<<&arr[0]<<std::endl;
    std::cout<<"value of ar: "<<ar<<std::endl;
    std::cout<<"value of ar1: "<<ar1<<std::endl;
    std::cout<<"value of *ar: "<<*ar<<std::endl;
    std::cout<<"value of *ar1: "<<*ar1<<std::endl;
    std::cout<<"value of *(ar+1): "<<*(ar+1)<<std::endl;
    std::cout<<"value of *(ar1+1): "<<*(ar1+1)<<std::endl;
    std::cout<<"value of ar[0]: "<<ar[0]<<std::endl;//some garbage value
    std::cout<<"value of ar1[0]: "<<ar1[0]<<std::endl;//some garbage value
    std::cout<<"value of sizeof(ar): "<<sizeof(ar)<<std::endl;
    std::cout<<"value of sizeof(int): "<<sizeof(int)<<std::endl;
    std::cout<<"value of sizeof(arr): "<<sizeof(arr)<<std::endl;
    std::cout<<"value of sizeof(ar1): "<<sizeof(ar1)<<std::endl;
}

the following is the output for this code:

add of arr[0] :0x7fffe6054ba0
value of ar: 0x7fffe6054ba0
value of ar1: 0x7fffe6054ba0
value of *ar: 21
value of *ar1: 21
value of *(ar+1): 2
value of *(ar1+1): 2
value of ar[0]: 21
value of ar1[0]: 21
value of sizeof(ar): 40
value of sizeof(int): 4
value of sizeof(arr): 40
value of sizeof(ar1): 8

as you can see , the only difference I can spot is the size of reference is different than the size of pointer. In fact value of both reference and pointer is the first element of the array. Even the pointer arithmetic works the same way for both of them. The size of reference is int*10 vs size of pointer which is 8. What is going on here exactly ? How are these two different and is there a standard practise as to when to use a reference or a pointer ?

Upvotes: 1

Views: 328

Answers (2)

mediocrevegetable1
mediocrevegetable1

Reputation: 4217

A simplified explanation:

A pointer is a type that needs to be large enough to be able to store any address. On your system, that needed size is 8 bytes. You can do things with a pointer without actually changing a variable it is pointing to as well. sizeof will not give the size of the array, but of the pointer. Note that sizeof *ar1 should not give the size either, it simply gives the size of the first element of the array, which is an int.

A reference is basically syntactic sugar over a pointer that has some extra power for true pass-by-reference. For both references and pointers, the compiler could generate identical/very similar assembly/machine code with both references and pointers. For example, these two functions:

int foo(int &bar)
{
    return ++bar;
}
int baz(int *bar)
{
    return ++(*bar);
}

Generate identical assembly with GCC 10.2 and -O1 (checked with Compiler Explorer):

foo(int&):
        mov     eax, DWORD PTR [rdi]
        add     eax, 1
        mov     DWORD PTR [rdi], eax
        ret
baz(int*):
        mov     eax, DWORD PTR [rdi]
        add     eax, 1
        mov     DWORD PTR [rdi], eax
        ret

(The generated assembly is identical for both functions at -O0, -O2 and -O3 too)

As you can see, it's exactly the same.

But yes, references have some more power over pointers. As you can see, sizeof gave the actual size of the array, whereas with the pointer, it simply gave the size of the pointer. Also, with the case of const T & and T && a reference can accept an rvalue too, which a pointer cannot.

Upvotes: 2

prehistoricpenguin
prehistoricpenguin

Reputation: 6326

The size of reference is int*10 vs size of pointer which is 8.

A reference is an alias, so the size of reference is int*10, which is the same as sizeof(arr)

How are these two different and is there a standard practice as to when to use a reference or a pointer?

Prefer to use reference when you don't need to control the lifetime of the object. When you find that reference can't meet your requirement then we have to use pointers.

Reference vs pointer:

  • reference must be inited
  • pointer doesn't have to be inited
  • reference can be dangling, pointers can be dangling too
  • the pointer which controls the ownership of resource needs to be deleted to avoid resource leaking(We can use smart pointers to avoid it)

You may also read Google c++ style guide to get more information on choice of reference vs pointer

Upvotes: 2

Related Questions