1

I have the following class, which includes a copy constructor:

Header File: Fred.h

namespace foo {


class Fred {
private:
    int _x;
    int _y;


public:
    Fred();                         // Default constructor
    Fred(Fred const &other);        // Copy constructor
    Fred(int x, int y);             // Regular parameters
    ~Fred();                        // Destrcutor

};


}

Implementation File: Fred.cpp

#include "Fred.h"
#include <iostream>

foo::Fred::Fred(){
    _x = 0;
    _y = 0;

    std::cout << "Calling the default constructor\n";
}

foo::Fred::Fred(Fred const &other){

    _x = other._x;
    _y = other._y;

    std::cout << "Calling the copy constructor";
}

foo::Fred::Fred(int x, int y){
    _x = x;
    _y = y;

    std::cout << "Calling the convenience constructor\n";
}

foo::Fred::~Fred(){

    std::cout << "Goodbye, cruel world!\n";
}

I was expecting to see the destructor called when it got out of scope, instead, the copy constructor was called and then the destructor. Why was a copy created? Am I leaking memory?

using namespace foo;

int main(int argc, const char * argv[])
{



    {
        Fred f2 = *new Fred();

    } // I was expecting to see a destructor call only


    return 0;
}
cfischer
  • 24,452
  • 37
  • 131
  • 214

6 Answers6

5

That's because you're using the memory leak operator *new.

Objects allocated with new are never deleted automatically; only by an explicit use of delete. Your code dynamically allocates an object, copies it to f2, and then loses the only pointer to the dynamic object.

If you simply want to create a local object:

Fred f2;

When you actually need dynamic allocation (in other words, if the object needs to outlive the current scope), always use RAII objects, such as smart pointers, to avoid memory leaks. For example:

std::unique_ptr<Fred> f2(new Fred);   // C++11 - no "delete" needed
auto f2 = std::make_unique<Fred>();   // C++14 - no "new" or "delete" needed
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
4

Yes, the code leaks memory: new Fred() allocates an object on the heap, but the code doesn't save the returned pointer and doesn't delete the object.

The reason the copy constructor is called is that the creation of f2 copies the argument, just as if it had been written

Fred f2(*new Fred());
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
4

A copy is created because you are copying the dynamically allocated object created by this expression:

new Fred();

into Fred f2:

Fred f2 = *new Fred(); // f2 is a copy of RHS object

The destructor of the dynamically alloceted object is never called. This is a memory leak. Only f2's destructor will be called.

See this demo.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 1
    I have one question for just for clearing my doubt. In this case we have two Fred object one created dynamically on heap using new and another on stack by the calling the copy-construction. So why the destructor for second object didn't get called here? – Vivek Kumar Aug 23 '13 at 12:42
  • @dearvivekkumar It should get called. See [this demo](http://ideone.com/3DJ4Cm#view_edit_box), which has three objects constructed and two destroyed. – juanchopanza Aug 23 '13 at 12:54
4

What you probably meant to write was:

Fred f2 = Fred();

And since Fred has a user-defined default constructor, you can shorten that to:

Fred f2;
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
2

C++ allocates variables on the stack by default. When you write a sentence like Foo* foo = new Foo; what you are doing is to allocate a pointer on the stack wich points to a new object you are allocating on the heap.
Your code forgets to release the memory used by the object pointed by the pointer, so the object is never released, and its destructor never called.

I suggest you to checkout this thread: When should I use the new keyword in C++?

Community
  • 1
  • 1
Manu343726
  • 13,969
  • 4
  • 40
  • 75
1

By dereferencing your newly created object on the heap and assigning it to Fred f2 you implictly call the copy constructor. It's the same as

Fred f1;
Fred f2 = f1;

Besides you "lose" your pointer to the object on the heap, which will not be deleted automatically --> Memory Leak.


If you aren't using RAII (but you should), you need to clear up manually. Which would look like:

using namespace foo;

int main(int argc, const char * argv[])
{



    {
        Fred* pF2 = new Fred();  // keep the pointer to manually delete

    } 
    // no destructor call even though scope is left --> delete manually
    delete pF2;
    pF2 = 0;

    return 0;
}
Sambuca
  • 1,224
  • 18
  • 30