www.digitalmars.com         C & C++   DMDScript  

c++ - operator return value - d.cpp

reply mesti_mudam yahoo.com writes:
this is a dummy matrix algebra library example. to avoid matrix creation like
"Matrix a, b(a), c=a;" the copy-ctor is private. currently it compiles and runs
nicely. when the commented version of operator* is used, it doesnt compile and
give this error message:

OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

d2.obj(d2)
Error 42: Symbol Undefined ??0Matrix  AAE ABV0  Z (syscall Matrix::Matrix(Matrix
const &))

--- errorlevel 1


is this an error of dmc, or should i not try to make copy-ctor private?
Jul 13 2006
parent reply Heinz Saathoff <newshsaat arcor.de> writes:
Hello,

 this is a dummy matrix algebra library example. to avoid matrix creation like
 "Matrix a, b(a), c=a;" the copy-ctor is private. currently it compiles and runs
 nicely. when the commented version of operator* is used, it doesnt compile and
 give this error message:
 
 OPTLINK (R) for Win32  Release 7.50B1
 Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
 
 d2.obj(d2)
 Error 42: Symbol Undefined ??0Matrix  AAE ABV0  Z (syscall
Matrix::Matrix(Matrix
 const &))

You return a Matrix-Object by value in both versions of 'operator*'. The semantics say that the local Matrix-Object is copied to the function result with the copy constructor. Therefore the copy constructor must be accessible in both cases. The compiler is allowed to optimize the actual copy away (constructing the local obkect directly in the return-object. Therefore the message is correct, but IMO too late (the compiler should detect this because the copy constructor isn't accessible). Even if the compiler is allowed to optimize the copy the semantics of applying the copy-constructor must be checked! - Heinz
Jul 18 2006
parent reply mesti_mudam yahoo.com writes:
well it is apparently return by value, but in reality it is not, or something in
between let's say.

in the current verison of the code, for c=a*b, the compiler allocates a temp
space in the caller and passes a pointer-to-that-temp-space to the operator*.
the res object in the uncommented version of operator* is not actually a local
object in operator*, its space was allocated in the caller, it is just
initialized in operator* with a constructor. note that the compiler can do this
because it knows in compile time that res will be the result.

in the uncommented version of operator*, the compiler cannot determine in
compile time which object will be returned, res or res2, so it chooses to do the
following:
again a temp space is allocated in the caller, and a pointer-to-that-temp-space
is passed to operator* (in fact this is always done). then according to the
result of the if statement, a 'local' object is created, res or res2, and then
the temp space is initialized with, not a constructor but, a copy constructor
where res or res2 is a parameter to that copy constructor.

the following is also possible:
instead, the temp space can be initiliazed, according to the result of if
statement, with (possibly) different constructors with (possibly) different
parameters and then operator* returns. there is no need to create local objects
and use a copy constructor (with a parameter of a local object) to initialize
the temp spcace.


thx



In article <MPG.1f26af1f11c95889989700 news.digitalmars.com>, Heinz Saathoff
says...
Hello,

 this is a dummy matrix algebra library example. to avoid matrix creation like
 "Matrix a, b(a), c=a;" the copy-ctor is private. currently it compiles and runs
 nicely. when the commented version of operator* is used, it doesnt compile and
 give this error message:
 
 OPTLINK (R) for Win32  Release 7.50B1
 Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
 
 d2.obj(d2)
 Error 42: Symbol Undefined ??0Matrix  AAE ABV0  Z (syscall
Matrix::Matrix(Matrix
 const &))

You return a Matrix-Object by value in both versions of 'operator*'. The semantics say that the local Matrix-Object is copied to the function result with the copy constructor. Therefore the copy constructor must be accessible in both cases. The compiler is allowed to optimize the actual copy away (constructing the local obkect directly in the return-object. Therefore the message is correct, but IMO too late (the compiler should detect this because the copy constructor isn't accessible). Even if the compiler is allowed to optimize the copy the semantics of applying the copy-constructor must be checked! - Heinz

Jul 18 2006
parent reply Heinz Saathoff <newshsaat arcor.de> writes:
Hello,

 well it is apparently return by value, but in reality it is not, or something
in
 between let's say.

Even if not implemented as 'copy by value' the semantics is 'copy the local object to the function result with the copy-constructor'. Therefore the copy constructor must be accessible!
 in the current verison of the code, for c=a*b, the compiler allocates a temp
 space in the caller and passes a pointer-to-that-temp-space to the operator*.
 the res object in the uncommented version of operator* is not actually a local
 object in operator*, its space was allocated in the caller, it is just
 initialized in operator* with a constructor. note that the compiler can do this
 because it knows in compile time that res will be the result.

This optimization is allowed by the standard DMC implements it. Nonetheless, the compiler has to check accessibility as if this optimization is not done. If the copy-constructor is private it must give a error message.
 in the uncommented version of operator*, the compiler cannot determine in
 compile time which object will be returned, res or res2, so it chooses to do
the
 following:
 again a temp space is allocated in the caller, and a pointer-to-that-temp-space
 is passed to operator* (in fact this is always done). then according to the
 result of the if statement, a 'local' object is created, res or res2, and then
 the temp space is initialized with, not a constructor but, a copy constructor
 where res or res2 is a parameter to that copy constructor.

Ack. But in this case the copy-constructor is used even if (semantically) unaccessible. Therefore the error-message should come from the compiler and not from the linker!
 the following is also possible:
 instead, the temp space can be initiliazed, according to the result of if
 statement, with (possibly) different constructors with (possibly) different
 parameters and then operator* returns. there is no need to create local objects
 and use a copy constructor (with a parameter of a local object) to initialize
 the temp spcace.

But still the accessibility rules apply, even if the copy-constructor call can be (and is allowed to be) optimized away. - Heinz
Jul 20 2006
parent reply mesti_mudam yahoo.com writes:
well what im saying is, if u r not using it, then its access rights doesnt
matter for u (compile it with -o -6). forcing something to be public which is
not used at all (in the current verison of code) is stupid, if the C++ standard
says it should be like that, then the standard is stupid. even in the 2nd
verison of operator* (with if), copy-ctor can be avoided and the code will be
better faster, and u still shouldnt need to make copy-ctor public. then when do
we need it? we need it only when we have to. and how does one prevent the user
from creating objects like "Matrix b(a), c=a;" which use copy-ctor. in fact
there r (should be) 2 kinds of copy-ctors. one which is called explicitly by the
programmer via something like "Matrix b(a), c=a;", and one that the compiler
uses for temp objects it creates.

In article <MPG.1f294e0fe5e8652d989701 news.digitalmars.com>, Heinz Saathoff
says...
Hello,

 well it is apparently return by value, but in reality it is not, or something
in
 between let's say.

Even if not implemented as 'copy by value' the semantics is 'copy the local object to the function result with the copy-constructor'. Therefore the copy constructor must be accessible!
 in the current verison of the code, for c=a*b, the compiler allocates a temp
 space in the caller and passes a pointer-to-that-temp-space to the operator*.
 the res object in the uncommented version of operator* is not actually a local
 object in operator*, its space was allocated in the caller, it is just
 initialized in operator* with a constructor. note that the compiler can do this
 because it knows in compile time that res will be the result.

This optimization is allowed by the standard DMC implements it. Nonetheless, the compiler has to check accessibility as if this optimization is not done. If the copy-constructor is private it must give a error message.
 in the uncommented version of operator*, the compiler cannot determine in
 compile time which object will be returned, res or res2, so it chooses to do
the
 following:
 again a temp space is allocated in the caller, and a pointer-to-that-temp-space
 is passed to operator* (in fact this is always done). then according to the
 result of the if statement, a 'local' object is created, res or res2, and then
 the temp space is initialized with, not a constructor but, a copy constructor
 where res or res2 is a parameter to that copy constructor.

Ack. But in this case the copy-constructor is used even if (semantically) unaccessible. Therefore the error-message should come from the compiler and not from the linker!
 the following is also possible:
 instead, the temp space can be initiliazed, according to the result of if
 statement, with (possibly) different constructors with (possibly) different
 parameters and then operator* returns. there is no need to create local objects
 and use a copy constructor (with a parameter of a local object) to initialize
 the temp spcace.

But still the accessibility rules apply, even if the copy-constructor call can be (and is allowed to be) optimized away. - Heinz

Jul 21 2006
parent Heinz Saathoff <newshsaat arcor.de> writes:
Hello,

 well what im saying is, if u r not using it, then its access rights doesnt
 matter for u (compile it with -o -6). 

This is an _allowed_ optimization, that's what the standard says. A non- optimizing compiler would use the copy constructor to copy the local object to the returned object.
 forcing something to be public which is
 not used at all (in the current verison of code) is stupid, if the C++ standard
 says it should be like that, then the standard is stupid. 

The standard allows dumb compilers in code generation, but not in sematic checks ;-)
 even in the 2nd
 verison of operator* (with if), copy-ctor can be avoided and the code will be
 better faster, and u still shouldnt need to make copy-ctor public. 

Allowed optimization, but a compiler is not forced to do so! Therefore the constructor must be accessible!
 then when do
 we need it? we need it only when we have to. and how does one prevent the user
 from creating objects like "Matrix b(a), c=a;" which use copy-ctor. 

As far as I know the compiler is not allowed to optimize the copy constructor away. It's only allowed for function return values.
 in fact
 there r (should be) 2 kinds of copy-ctors. one which is called explicitly by
the
 programmer via something like "Matrix b(a), c=a;", and one that the compiler
 uses for temp objects it creates.

Why should the programmer have to write two (most times) identical constructors. I don't see a big benefit here. - Heinz
Jul 23 2006