From: Robert Billing on
I'm a long-tern C programmer who is trying to convert to C++, and as a
first project I have written a class that implements "infinite precision"
integer arithmetic. This hold integers in the following form:

int sign ; /* True if <0 */
int space ; /* Allocated bytes */
int used ; /* Bytes actually used */
unsigned char *val ; /* The value, held lsb first */

The val member is created with an invocation of new, and released by a
destructor.

I have implemented the operators =, +, -, *, /, %, <<, >>, &, |, ^, +=, -
=, *=, /=, %= <<=, >>=, &=, |=, ^= and the stream write <<. I also have
monadic +, - and ~. The bitwise operators are implemented on the
assumption that a negative integer is used in twos-compliment format with
the sign extended as required. There are also conversions to and from both
integer and string.

The value is held little-endian magnitude with a separate sign, and can be
of any size consistent with the local addressing length.

Most of this has worked with little trouble, in fact the last few
operators worked at the first attempt.

However I did run into one problem for which I found a workaround that I
think is rather messy. I'd like to know if there is a cleaner solution.

This is the relevant code, which converts an infinite int to a class
string at any base and with arbitrary options. The accumulator acc is set
to the absolute value of the number to be converted, and divisor to the
base. Repeated divisions are then used to generate the digits one at a
time. As the program stands - the working version is below - acc is set up
by a default constructor which sets zero, and then assigned from the
number to convert. I have overloaded the assignment operator with a
procedure that copies sign, allocates new memory for val and fills in
space and used.

/* Generic conversion to text. Number is left padded to width,
converted using base which can be 2 to 16. Flags define the
options, see header. */
string infinite_int::text ( int width, int base, int flags ) const
{
string res, txt_sign ;
infinite_int acc, divisor = base, quot, rem ;
int digit, fill ;

/* Convert the unsigned value */
acc = *this ;
acc . sign = 0 ;

THE PROBLEM is that if I don't do an explicit alignment, but write

infinite_int acc = *this ;

in the definitions it doesn't invoke my overloaded = operator, but simply
clones the input instance. This leaves two instances with the same value
of val, pointing at the same memory. When one of these is destroyed the
memory is freed, but the other continues to point to it. This can cause a
later crash.

Is there a way that I can make my overloaded = operator work when defining
a variable which is a class? Should I be providing an additional
constructor?
From: Paul Bibbings on
Robert Billing <unclebob(a)tnglwood.demon.co.uk> writes:
> THE PROBLEM is that if I don't do an explicit alignment, but write
>
> infinite_int acc = *this ;

Despite the superficial similarity of syntax the above effects
initialization, *not* assignment. your overloaded assignment operator
is, therefore, naturally not considered here.

In effect you are invoking the class' copy constructor, but even here
there can be complications in some clearly-defined instances owing to
the fact that the implementation is permitted to elide this even if the
copy-ctor has side effects.

You haven't said whether or not you have overloaded your copy
constructor, but you might want to do this to obtain the semantics that
you require, and then you might want to consider invoking it explictly
using:

infinite_int acc(*this);

in place of the above.

> in the definitions it doesn't invoke my overloaded = operator, but simply
> clones the input instance. This leaves two instances with the same value
> of val, pointing at the same memory. When one of these is destroyed the
> memory is freed, but the other continues to point to it. This can cause a
> later crash.
>
> Is there a way that I can make my overloaded = operator work when defining
> a variable which is a class? Should I be providing an additional
> constructor?


Regards

Paul Bibbings
From: Robert Billing on
We, the Senate of Arcturus, take note that Paul Bibbings said:

> Robert Billing <unclebob(a)tnglwood.demon.co.uk> writes:
>> THE PROBLEM is that if I don't do an explicit alignment, but write
>>
>> infinite_int acc = *this ;
>
> Despite the superficial similarity of syntax the above effects
> initialization, *not* assignment. your overloaded assignment operator
> is, therefore, naturally not considered here.
>
> In effect you are invoking the class' copy constructor, but even here
> there can be complications in some clearly-defined instances owing to
> the fact that the implementation is permitted to elide this even if the
> copy-ctor has side effects.

Ah, thanks! The penny suddenly drops with a deafening clang. I now see
what's going on.