Thread overview
operator return value - d.cpp
Jul 13, 2006
mesti_mudam
Jul 18, 2006
Heinz Saathoff
Jul 19, 2006
mesti_mudam
Jul 20, 2006
Heinz Saathoff
Jul 21, 2006
mesti_mudam
Jul 24, 2006
Heinz Saathoff
July 13, 2006
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?


July 18, 2006
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
July 19, 2006
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


July 20, 2006
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
July 21, 2006
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


July 24, 2006
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