Copy Constructor Craziness

U

Unknown Poster

The behavior I'm seeing in Perl 5.6 contradicts what I understand
about copy constructors - specifically, when they are autogenerated.

# $f is a reference to an object
my $g = $f;
print "\$g = $g, ";
++$g;
print "after ++, \$g = $g, \$f = $f\n"; # The value of $g changes,
but the
# value of $f does not!

There is no overloading of "=" - no explicit copy constructor in the
class.
There is also no overloading of "++" in the class, but it is
apparently
autogenerated from the overloading of "+".

This appears to conflict with information in "The Copy Constructor"
section
of Programming Perl, 3rd edition.
Without a copy constructor, it states that the following would happen:

"$copy = $original; # copies only the reference
++$copy; # changes underlying shared reference"

"If the copy constructor is required during the execution of some
mutator,
but a handler for = was not specified, it can be autogenerated as a
string
copy provided the object is a plain scalar and notsomething fancier."

There are two separate scalar values in every object of the class,
so I don't see why the copy constructor is apparently being
autogenerated
in this case.
 
B

Ben Morrow

The behavior I'm seeing in Perl 5.6 contradicts what I understand
about copy constructors - specifically, when they are autogenerated.

# $f is a reference to an object
my $g = $f;
print "\$g = $g, ";
++$g;
print "after ++, \$g = $g, \$f = $f\n"; # The value of $g changes,
but the
# value of $f does not!

There is no overloading of "=" - no explicit copy constructor in the
class.
There are two separate scalar values in every object of the class,
so I don't see why the copy constructor is apparently being
autogenerated in this case.

Please post a short *complete* program exhibiting the problem, and
explain how what it is doing differs from what you want it to do.

Ben
 
U

Unknown Poster

Steve May said:
so, assuming that $f is indeed a scalar reference $g now equals
something like:

SCALAR(0x80545ac)

Is this what you want/expect?


Hmmmm... doesn't look like it, at least it looks like you are
trying to increment a scalar....




#! /usr/bin/perl -w
use strict;

my $base = 4;

my $f = \$base;

my $g = $f;
print "g is $g and f is $f\n";


$$g++;

print "g is $$g, and f is $$f\n";



s.

# the code for the Rational class is too long to include in a post
# an object represents a fractional number, so its two data members
# are scalars - the fraction's numerator and denominator

use Rational;
use warnings;
use strict;

my $f = Rational->new(1, 7) ;
my $g = $f;
print "\$g = $g, ";
++$g;
print "after ++, \$g = $g, \$f = $f\n";

------------------------------------------

output is:
$g = 1/7, after ++, $g = 8/7, $f = 1/7

I'm not arguing that this result is "wrong", just that it appears
to be inconsistent with what Programming Perl states about
copy constructors. Again, I do not overload "=" for the
Rational class. Copy constructors are supposedly autogenerated
only when "the object is a plain scalar". I'm not sure what that
means, but don't see how a class with two scalars qualifies for
autogeneration.
 
A

Aaron Sherman

use Rational;
use warnings;
use strict;

my $f = Rational->new(1, 7) ;
my $g = $f;
print "\$g = $g, ";
++$g;
print "after ++, \$g = $g, \$f = $f\n";

That does, indeed look wrong, but without seeing the code for
Rational, it's hard to tell. Clearly you must be overloading
stringification and ++, but if you're not overloading = as well, then
I'm confused.
 
J

Jay Tilton

(e-mail address removed) (Unknown Poster) wrote:

: # the code for the Rational class is too long to include in a post

You could still trim it down to only the parts necessary to demonstrate
what you describe. Like, say,

package Rational;
use overload
'""' => sub { "$_[0][0]/$_[0][1]" },
'+' =>
sub {
my $obj = shift;
my( $num, $dem ) = @$obj;
$num += $_[0] * $dem;
ref($obj)->new( $num, $dem );
},
;
sub new { my $c = shift; bless [@_], $c }

: # an object represents a fractional number, so its two data members
: # are scalars - the fraction's numerator and denominator
:
: use Rational;
: use warnings;
: use strict;
:
: my $f = Rational->new(1, 7) ;
: my $g = $f;
: print "\$g = $g, ";
: ++$g;
: print "after ++, \$g = $g, \$f = $f\n";
:
: ------------------------------------------
:
: output is:
: $g = 1/7, after ++, $g = 8/7, $f = 1/7
:
: I'm not arguing that this result is "wrong", just that it appears
: to be inconsistent with what Programming Perl states about
: copy constructors. Again, I do not overload "=" for the
: Rational class. Copy constructors are supposedly autogenerated
: only when "the object is a plain scalar". I'm not sure what that
: means, but don't see how a class with two scalars qualifies for
: autogeneration.

Back up a couple pages to see:

The ++$a operation can be autogenerated using $a+=1 or $a=$a+1, ....
^^^^^^^
That second part is a tricky read. Is the '=' in there supposed to be a
copy constructor, or does it represent an ordinary, non-overloaded
assignment?

There's a conspicuous change in the 5.8 docs:

The ++$a operation can be expressed in terms of $a+=1 or $a+1, ....

As I read it, that means that the class will use an available copy
constructor to do ++$a, but it can finesse its way around a copy
constructor's absence without having to autogenerate one.
 
U

Unknown Poster

Back up a couple pages to see:

The ++$a operation can be autogenerated using $a+=1 or $a=$a+1, ....
^^^^^^^
That second part is a tricky read. Is the '=' in there supposed to be a
copy constructor, or does it represent an ordinary, non-overloaded
assignment?

The next sentence is also verrrry interesting:
"However, this does not trigger the copying behavior that a real
++ operator would."

Horsefeathers! That is exactly what is happening in this case.
A copy constructor is being autogenerated.
There's a conspicuous change in the 5.8 docs:

The ++$a operation can be expressed in terms of $a+=1 or $a+1, ....

As I read it, that means that the class will use an available copy
constructor to do ++$a, but it can finesse its way around a copy
constructor's absence without having to autogenerate one.

In the example earlier in the thread, "++" is not EXPLICITLY
overloaded, but "+" is (and += is not). The copy constructor
is being autogenerated in this case - it is self-evident in
that $g and $f end up referencing different objects, while
there was no overloading of "=". The text of Programming Perl 3E
seems to be wrong, or at least very misleading, because I don't see
any justification for this autogeneration.

Now, for another intersesting result. When I do explicitly overload
"++" in the class, Perl bombs out at "++g" with an error message stating:
"... Operation '=', no method found, argument in overloaded
package Rational ..."

This seems more in line with what was stated in the book - that
autogeneration of a copy constructor (only?) takes place if the
class is "a plain scalar".

As Ricky Ricarco would say, "Somebody has some splainin to do!".
 
J

Jay Tilton

(e-mail address removed) (Unknown Poster) wrote:

: The next sentence is also verrrry interesting:
: "However, this does not trigger the copying behavior that a real
: ++ operator would."
:
: Horsefeathers! That is exactly what is happening in this case.
: A copy constructor is being autogenerated.

You are mistaken. There is no copy constructor involved at all.

: In the example earlier in the thread, "++" is not EXPLICITLY
: overloaded, but "+" is (and += is not). The copy constructor
: is being autogenerated in this case - it is self-evident in
: that $g and $f end up referencing different objects, while
: there was no overloading of "=".

If the overloaded '+' returns a new object, as it does in the pared-down
demonstration class I wrote in the previous article, how could you
sensibly expect an autogenerated '++' not to? This is not any kind of
evidence that a copy constructor is being used.

If your own overloaded '+' does not return a new object, it's time for
you to show the code for your overloaded operators.

: The text of Programming Perl 3E
: seems to be wrong, or at least very misleading,

The book is at least 3.5 years behind the Perl docs' revision state.
Save accusations of incorrectness for the current version.

Obsolescence issues aside, the fourth paragraph in the "The Copy
Constructor (=)" section of chapter 13 plainly says:

The need for copying is recognized only by mutators such as ++ or

+= . . . . If the operation is autogenerated via +, . . . then no

copying occurs, . . . .

What do you find wrong or misleading about that?

: because I don't see any justification for this autogeneration.

You're chasing phantoms here. There is no autogenerated copy
constructor.

: Now, for another intersesting result. When I do explicitly overload
: "++" in the class, Perl bombs out at "++g" with an error message stating:
: "... Operation '=', no method found, argument in overloaded
: package Rational ..."

Yes. If you're overloading a mutator, there needs to be a copy
constructor. If you're letting the mutator be autogenerated, a copy
constructor is irrelevant.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top