-2

I am reading the book c++ primer plus and I feel confused about the reference variables and pointers. Here are two pieces of code extracted from page 400 of the book.

const free_throws & clone(free_throws & ft)
{
   free_throws * pt;
   *pt = ft;
   return *pt;
}


const free_throws & clone2(free_throws & ft)
{
    free_throws newguy;
    newguy = ft;
    return newguy;
 }

The book said that the first one is okay but the second one is invalid. Is it true that a pointer variable will still exist after the function terminates even if it is declared within the function? Another question is why can we omit the new keyword in the first piece of code? If we can just create a nameless structure and assign something to it, why do we need the new keyword? Thank you in advance.

For the first one, the book provided a few lines of explanation.

The first statement creates a nameless free_throws structure. The pointer pt points to the structure, so *pt is the structure. The code appears to return the structure, but the function declaration indicates that the function really returns a reference to this structure.
Jason
  • 11
  • 1

1 Answers1

3

Both functions have problems. The first function's problem is that pt does not point at a valid free_throws object, so doing *pt = ft; gives you undefined behaviour (you are assigning to a non-existent object). The second function's problem is that you're returning a reference to a local variable which will be destroyed when the function returns (a dangling reference).

Is it true that a pointer variable will still exist after the function terminates even if it is declared within the function?

No. A locally declared pointer is just like any other locally declared object - it will be automatically destroyed at the end of the function. The object that it points at may have a different lifetime, however.

Another question is why can we omit the new keyword in the first piece of code? If we can just create a nameless structure and assign something to it, why do we need the new keyword?

You can't.

If you want to create an object that lasts beyond the scope of a function, you can use a new-expression (like new free_throws()). This creates an object with dynamic lifetime, which you must later destroy manually with delete.

To demonstrate, your first function would be okay (at least not invoke undefined behaviour) if you dynamically allocated a free_throws object for pt to point to:

const free_throws & clone(free_throws & ft)
{
   free_throws * pt = new free_throws();
   *pt = ft;
   return *pt;
}

However, it's still a really bad function because it really doesn't make it clear that the object being returned needs to be destroyed manually. Good C++ code will manage the ownership of dynamically allocated objects using smart pointers. At the very least, you should use raw pointers, simply because C++ developers know to look out for them, and document that your function dynamically allocates the objects it returns.

However, it is typically much better to write a function without any dynamic allocation at all. If you were to do that with this clone function though, you would just discover how pointless it is. Might as well just use the copy constructor instead of writing an extra function.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324