| > Is this expected behavior?
For a broken program, yes. :-)
He needs a copy constructor for his class,
SimpleString(const SimpleString &);
with definition something like
SimpleString::SimpleString(const SimpleString &rhs)
{
// don't use this to copy construct an object with itself!
if (rhs.count > 0) {
count = rhs.count;
buffer = new char[count];
memcpy(buffer, rhs.buffer, count);
} else {
count = 0;
buffer = 0;
}
}
He also needs a similar assignment operator, but just the copy
constructor here would fix the small example.
> The debugger shows that new was returning the same address in both
> calls to the non-default constructor.
> SimpleString S1;
> SimpleString S2 = "String S2";
> SimpleString S3("String S3");
S1 is constructed with SimpleString::SimpleString() and
S3 is constructed with SimpleString::SimpleString(char *).
The customer thinks S2 is also being constructed with
SimpleString::SimpleString(char *) but he is wrong. A
temporary object is being constructed with
SimpleString::SimpleString(char *) and S2 is being constructed
with the compiler-synthesized copy constructor using that
temporary. Then the temporary is destroyed. So the sequence
of new char [] / delete char [] operations is
temporary.buffer = new char[10];
S2.buffer = temporary.buffer;
delete [] temporary.buffer;
// S2.buffer is now a dangling pointer
S3.buffer = new char[10]; // returns same pointer as S2.buffer
That's why the class needs its own copy constructor and
assignment operator.
Dan
|