2

I'm learning C++ and I am trying to understand when to assign a pointer to a base class to an object created using the new keyword as opposed to creating an object normally and setting a pointer equal to the address of the object?
Effectively is there any difference in the methods implemented below.

#include<iostream>
using namespace std;

class Base
{
public:
    virtual void show() { cout<<" In Base \n"; }
};

class Derived: public Base
{
public:
    void show() { cout<<"In Derived \n"; }
};

int main(void)
{

    Base *bp = new Derived();
    bp->show();

    Derived d1;
    Base *bp = &d1;
    bp->show();


    return 0;
}
netleap tom
  • 143
  • 1
  • 9
  • 5
    As for your title: Almost never. –  Jan 29 '18 at 18:08
  • 1
    related: https://stackoverflow.com/q/6500313/ – RHertel Jan 29 '18 at 18:12
  • `Effectively is there any difference in the methods implemented below` The only difference is that the first one uses heap while the second one uses stack. Allocating on stack is faster because it doesn't require `new` call which has some overhead (by the way, you didn't `delete` in first example, hence memory leak). On the other hand lifetime of things on stack is restricted - they only live until the containing scope (i.e. the function) exits. – freakish Jan 29 '18 at 18:12
  • 4
    Possible duplicate of [When should I use the new keyword in C++?](https://stackoverflow.com/questions/655065/when-should-i-use-the-new-keyword-in-c) – RHertel Jan 29 '18 at 18:13
  • 3
    @RHertel Too bad that's an old question. It's in need a more modern answer. A quick search shows that the terms `make_unique` and `make_shared` don't show up at all. As TheDude commented, a modern answer should say "Almost Never". – François Andrieux Jan 29 '18 at 18:29
  • @FrançoisAndrieux Good point. I retracted my close vote. – RHertel Jan 30 '18 at 06:05
  • @RHertel Though the answers are unfortunately out of date, it seems to me like the questions are still duplicates. I feel the best course of action would be to close this question as a duplicate and write a better answer for the other question. – François Andrieux Jan 30 '18 at 14:33

3 Answers3

1

The only difference - in your code at least - is in how lifetime is managed,

The first object is dynamically allocated (created when the programmer chooses, at run time) and will continue to exist until a corresponding delete expression. Since there is no delete expression, the object will never be released (although modern operating systems will typically reclaim memory as the program exits, that is not strictly required). If you were to add a statement that does delete bp, it will have undefined behaviour, since Base does not have a virtual destructor.

The second case is a variable of automatic storage duration, so ceases to exist when the enclosing block ends. It will cease to exist as main() returns.

In your code as shown, there will be no visible difference in output. That does not mean the two cases work the same way.

Peter
  • 32,539
  • 3
  • 27
  • 63
0

The formula is pretty simple:

1) If you use new, you are allocating memory (on the heap) for the newly created object. Your variable (pointer) points to that memory region. You should delete the created object (through its pointer) at some point yourself.

Referring to your example:

Base *bp = new Derived();
bp->show();
delete bp;
bp = NULL; // this is good practice, NULLing the pointer after deleting 
           // the referenced memory

2) If you just have a (non pointer) local variable, then the memory is automatically allocated for it on the function's stack. Memory is automatically freed when the execution point leaves that function. If you just have a pointer to a local variable, you don't need to free (delete) the memory.

Derived d1;
Base *bp = &d1;
bp->show();
// no need to free

However, it's better to do just this:

Derived d1;
d1.show();

Simpler.

Pablo Santa Cruz
  • 162,219
  • 30
  • 224
  • 277
  • 1
    You forgot to say _"almost never use new directly"_ use a smart pointer instead. – Richard Critten Jan 29 '18 at 18:27
  • @Richard Not to mention that the shown example code is prone to memory leaks if `bp->show();` throws an exception. –  Jan 29 '18 at 19:02
0

The difference is in how your memory is being allocated. If you use your first definition, you are using memory from the heap, which is essentially boundless (within system constraints obviously), if you allocate the object the second way you are using the stack which has a finite set of memory allocated to it for a given process running it. An example where this could become an issue is when you are creating a ton of objects on your stack (E.g., for a video game) and that stack becomes full, then you will get a stack over flow error returned. This has happened to me once, and then you must leverage the power and knowledge of the heap.

bmc
  • 671
  • 11
  • 15