1

Consider the following simple code.

    struct test
    {
      test(int n):numelements(n){ arr = new int[numelements] }

      int numelements;
      int* arr;

      ~test()
       {
          delete[]  arr;
       }
    }

   void foo_ref(test& x,n)
   {
       // set first n elements of the array x.arr to random numbers
   }

  void foo_ptr(test* x,n)
   {
       // set first n elements of the array x->arr to random numbers
   }

    int main(void)
    {
     test mystruct(1000000);
     foo_ref(mystruct,20);
     // foo_ptr(&mystruct,20); 


     return 0;
   }

In the above code, foo_ref and foo_ptr perform exactly the same operations on the object it refers to viz. mystruct. However foo_ref passes the object by reference and foo_ptr by means of pointers.

In both cases where is the destructor of the object invoked? I know the standard answer for this question always is "when the scope of an object ends"

But consider the case of passing by reference. Within the body of foo_ref mystruct has the scope of that function. So won't the destructor of the object be invoked at the end of the function foo_ref?

Maybe my confusion has to do with the understanding of the scope of something. Please let me know where I am erring in my reasoning.

smilingbuddha
  • 14,334
  • 33
  • 112
  • 189
  • 2
    You know `: numelements(n), arr(new int[numelements])` is valid, too, as long as `numelements` is declared before `arr` in your class. – chris Sep 07 '12 at 23:11
  • @ Mark see edit. they are just functions which say initialize some elements or whatever – smilingbuddha Sep 07 '12 at 23:16
  • 3
    The scope of the *reference* ends. That doesn't destroy the object. – Hans Passant Sep 07 '12 at 23:17
  • 1
    To add onto Hans's point, A reference going out of scope will not affect the object. However, an object going out of scope will leave any references to it to be dangling references. – chris Sep 07 '12 at 23:23

3 Answers3

3

I don't see any const references around here, therefore the answer is "no different in object lifetime between references and pointers".

const references bound to temporary expressions have a special rule extending the lifetime of the temporary object, but that doesn't apply to your code.

Your confusion probably stems from a statement made in a very popular FAQ, it goes something along the lines of "a reference IS the referred-to object". As you can see, this is not true. A reference is separate from the object it refers to, each has its own lifetime (and it's very rare to see this done correctly, but it's even legal for the lifetime of the reference to extend longer than the lifetime of the object)

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Thanks! I was under the impression that when a reference goes out of scope the destructor of that reference, (hence the object itself) gets invoked which would lead the memory to get freed. So by your answer I think this statement is wrong. – smilingbuddha Sep 07 '12 at 23:29
  • So when the destructor of a reference is called what exactly happens under the hood? I assume there is absolutely no connection with the destructor of the object it is referring to right? – smilingbuddha Sep 07 '12 at 23:33
  • There is no such thing as a destructor of a reference. *Objects* have destructors, and references are just a way of referring to objects. If there is a reference to an object somewhere, that has no effect on when/how the object is destroyed. Maybe you are confusing references with *reference counting*, which is a very different thing. – Oktalist Sep 07 '12 at 23:58
  • @Oktalist: Right, and that's all the proof you need that "the reference IS the object" is wrong. One has a destructor, the other doesn't, therefore they CAN'T be the same thing. – Ben Voigt Sep 08 '12 at 00:19
1

foo_ref will have a parameter, and it is the parameter that will have the scope of the function. Whether it is a pointer or a reference won't have any effect on the deletion of mystruct.

In the case where you pass a struct by value then the copy will be destroyed at the end of the function. If you do something silly like refer to the same arr in the copy then you could accidentally delete arr while the original struct is still using it. In that case you might want to use a shared pointer to track the memory used by arr instead of deleting it manually.

Neil
  • 54,642
  • 8
  • 60
  • 72
1

In the example code, the destructor for mystruct is called at the end of main.

Pointers When a pointer falls out of scope, nothing happens to the object being pointed to. The lifetime of the object stays whatever it would have been had the pointer never existed. There is, of course, an important detail: objects created by new/new[] exist until they are deleted/delete[]d, and memory allocated by malloc exists until it's freed.

References A reference is nothing more than an additional name for an existing object. With the exceptions of a const reference pointing at a temporary object, the reference's lifetime has no effect on the object-being-referred-to's-lifetime; the destructor is called when that object falls out of scope normally (a const reference to a temporary object keeps the temporary alive until the const reference falls out of scope).

Using the term "object" is a simplification, the pointer or reference really points at memory; it doesn't "track" the actual object in any way. For instance, it is possible to destroy an object being pointed to before the pointer falls out of scope, or to destroy an object being referenced before the reference falls out of scope. These invalid pointers/references are called "dangling pointers" and "dangling references" respectively:

int* i = new int(5);
int& j = *i;
delete i;

// i is now a dangling pointer, and j is now a dangling reference
Community
  • 1
  • 1
Max Lybbert
  • 19,717
  • 4
  • 46
  • 69
  • A reference is actually a name for a memory location, not the object. I explained that more thoroughly [here](http://stackoverflow.com/a/4715888/103167). – Ben Voigt Sep 07 '12 at 23:30
  • @BenVoigt Thanks. I've added a paragraph with that link. And, I'll admit that I hadn't thought of ways to create dangling references. – Max Lybbert Sep 07 '12 at 23:51
  • 1
    I'm not even talking about dangling references. It's legal to create a new object in the same memory as the old one, and as long as the type match, existing references work correctly with the new object. – Ben Voigt Sep 08 '12 at 00:18
  • @BenVoigt That's wild. I hadn't considered that. I made a minor edit to reflect that dangling pointers/dangling references aren't the only problem. – Max Lybbert Sep 08 '12 at 00:55