-1

I'm having difficulties understanding the following code:

class Base{
   Base(){/* do stuff */};
};

class Deriv: public Base{
   Deriv(){/* do stuff */};
};

// I have a problem understanding the purpose of the next line
Base &foo = *(new Deriv());
  • 3
    Well, that is a memory leak waiting to happen. But what is not clear to you exactly? It just dereferences the pointer and assigns it to a reference. – Quimby Feb 19 '23 at 11:01
  • 1
    It's essentially equivalent to something like `Base* foo_temp = new Deriv(); Base& foo = *foo_temp;` and then loosing `foo_temp` immediately. – Some programmer dude Feb 19 '23 at 11:04
  • @PanosKontogiannis There is nothing wrong with the line as it is. Having a reference is as good as having a pointer. – user17732522 Feb 19 '23 at 12:22
  • 1
    *it's impossible to check whether the memory has been allocated* In C++ you don't need to check if memory is allocated. By default, if memory is not allocated `std::bad_alloc` exception is thrown. If you want to check if memory was allocated manually, you need to add `(std::nothrow)` to new expression. – sklott Feb 19 '23 at 12:32
  • Thank you, it's clear now. The author just wanted to use `foo.member` instead of `foo->member` in the rest of the program if he simply used `Base* foo=new Deriv();` – Panos Kontogiannis Feb 19 '23 at 13:14

1 Answers1

1

First, you need to be familiar with Polymorphism, references, dereferencing and temporary object behavior.

  1. Every object of some Class can be represented as (can be treated as) an object of a Class that is higher in the hierarchy.

The most popular examples of this are animals. Many sources describe this topic with it.

class Animal {};

class Dog : public Animal {};

int main() {
    // All dogs are animals: OK
    Animal* a = new Dog();

    // Not every animal is a dog: Error
    Dog* d = new Animal()
}

Imagine you are creating a game, where your player has a pet.

class WongPlayer {
    Dog* pet;
}

If you put it this way, you will be able to have only Dog as pet.

class CorrectPlayer {
    Animal* pet;
}

In this case, you can have as pet any class that inherits from Animal.

This was just one simple example of the usage of Polymorphism.

  1. References. The best way of explaining what references are is to treat them as aliases. Creating a reference is completely identical of creating an alias. And all the restrictions are also well understood by this way.

Example:

int a = 5;
int& b = a; // b is alias of a
b = 3; // a = 3
  1. Dereferencing. new returns a pointer, so to work with the object it points to, you have to first dereference it.

Example:

int* val = new int(1);
val = 5; // Error can't assign int to pointer
*val = 5; OK
 delete val;
  1. Temporary objects, they are created and deleted immediately.

Example:

class A {
    public:
        A() { std::cout << "Created" << std::endl;}
        ~A() { std::cout << "Destroyed" << std::endl;}
}

int main {
    A();
    std::cout << "Should it be printed before destruction? No!" << std::endl;
    return 0;
}

In your case, you do the following: Allocate an object in heap and return its pointer.

new Deriv()

Dereference that pointer

*(new Deriv())

Create a reference and bind it with newly created object.

And here we start to have some problems. It is not a temporary object! Your object in heap never gets destroyed. It is a clear memory leak

I don't know why are you creating a reference. The best way is to create a pointer.

Base* ptr = new Deriv();

And then

delete ptr;

And that's it.

But yes, you can also delete it like this

Base& ref = *(new Deriv());
delete &ref;
sens
  • 71
  • 3