4

I'm training my C++ and I'm trying to write a library that'll be able to represent the following number using linked lists:

999999999 * ( [i=0]Σ[999999999] 1000000000 ^ i )

For example if my number was 711381450277869054011, it'll be represented like this:

711 * 1000000000^2 + 381450277 * 1000000000^1 + 869054011 * 1000000000^0

So, here is the struct of my LL and it's functions:

typedef struct node* ll;
struct node
{
    unsigned int data;
    ll next;
};

bool insert(ll&, unsigned int);
// ...
void copy(ll&, ll);
void destroy(ll&);

And here is my class of unsigned very long integers:

class uli
{
public:
    uli();
    ~uli();

    // <<, >>, =, operators...

    uli& operator +=(const uli&);
    uli& operator +=(char*);
    const uli operator +(const uli&);

private:
    ll head;
};

uli::uli()
{
    head = NULL;

    insert(head, 0);
}

uli::~uli()
{
    destroy(head);
}

+= operator works fine and I'm using it to overload the + operator.

The problem is that I can't make the method operator+() return a const uli without it being destroyed by the deconstructor before I get to use it.

const uli uli::operator +(const uli& rarg) // rarg: right argument
{
    uli larg; // left argument

    larg = *this;

    larg += rarg;

    return larg;
}
// returns an LL to somewhere ???? larg was destroyed.

Now I can't do Z = X + Y;

Jonas
  • 1,019
  • 4
  • 20
  • 33
  • 2
    Have you implemented the copy constructor? – zdan Mar 06 '12 at 02:28
  • no I didn't. is that critical? – Jonas Mar 06 '12 at 02:40
  • 1
    @jonas: Yes. If you don't create one, then the compiler has to, since that's how returning from a function works. And the compiler's version just copies the contents of the object -- including the `head` pointer -- rather than doing any sort of deep copy. – ruakh Mar 06 '12 at 02:45
  • I see. Is that why it can't temporary hold the returned uli? – Jonas Mar 06 '12 at 02:51

1 Answers1

6

You need to follow the Rule of Three,

If your class needs either

  • a copy constructor,
  • an assignment operator,
  • or a destructor,

then it is likely to need all three of them.

Root Cause of your problems:
In your case When you return a class uli instance by copy from overloaded operator + the compiler generated implicit copy constructor is used and it makes a shallow copy of your pointers, thus multiple pointers point to the same memory address and when one/some of them(temporary objects) gets destroyed the pointed to memory is deallocated through the destructor and that leaves others pointers (dangling)pointing to memory/content that does not exist.

Solution:
Follow the Rule of Three and implement your own copy constructor to perform Deep Copying of the involved pointers.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533