The temporary vs non-const reference love story

  • Thread starter =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunion?=
  • Start date
?

=?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunion?=

Hello.

Binding a temporary to a non-const reference is illegal. Everybody
should be tired of hearing that. So should I. But then I found myself
wondering about a small piece of code I was writing:

void cipher(unsigned long& xa, unsigned long& xb)
{
// ...
xa = // ...
xb = // ...
}

int main()
{
unsigned long a = 1111111;
unsigned long b = 2222222;
cipher(a, b);
}

The function cipher() is supposed to transform the two /long/ arguments
received. It might have had its arguments in the form of pointers, but
the author chose to allow users to use a simple, uncluttered cipher(a,
b) call. It might also have been made to return an object containing the
two ciphered values instead.

Which of the two alternatives aforementioned do you think is better? Is
there any other one I have overlooked?

Thank you,
 
W

wogston

void cipher(unsigned long& xa, unsigned long& xb)
{
// ...
xa = // ...
xb = // ...
}

int main()
{
unsigned long a = 1111111;
unsigned long b = 2222222;
cipher(a, b);
}

That is not illegal. This is:

int& foo()
{
int a = 7;
return a;
}


"int a" lives in stack. When you return from this function, the memory is
freed, so the reference is referring to memory that is not anymore in scope.
 
L

Larry Smith

That is not illegal. This is:
int& foo()
{
int a = 7;
return a;
}


"int a" lives in stack. When you return from this function, the memory is
freed, so the reference is referring to memory that is not anymore in
scope.

That's not the issue he was talking about. This is:

void foo(MyClass &Var)
{
// Whatever
}

foo(MyClass());

That's illegal because you can't pass a temporary to a non-const reference
parameter, only a *const* reference parameter. IOW, you need to make the
above parameter "const MyClass &". Actually, I don't understand what his
issue is. There's nothing wrong with the code he posted (he's not passing
temporaries).
 
O

Oplec

wogston said:
That is not illegal. This is:

int& foo()
{
int a = 7;
return a;
}


"int a" lives in stack. When you return from this function, the memory is
freed, so the reference is referring to memory that is not anymore in scope.

It is not illegal to return a reference to a local variable, but it is
wrong.
 
W

wogston

It is not illegal to return a reference to a local variable, but it is

What does 'wrong' mean in context of C++ programming? Since it appears you
want to imply that it is correct, as far as syntax of the language is
concerned, then there is only one question left:

Undefined, or defined behaviour? If defined, then how is it wrong? If it is
undefined, how it is not illegal?

So which wrong you mean? :)
 
R

Ron Natalie

wogston said:
What does 'wrong' mean in context of C++ programming? Since it appears you
want to imply that it is correct, as far as syntax of the language is
concerned, then there is only one question left:

Undefined, or defined behaviour? If defined, then how is it wrong? If it is
undefined, how it is not illegal?

Undefined behavior, but it is not ill-formed. That is, the compiler is not obligated
to detect and issue a diagnostic if you return a reference to an object that is about
to go out of scope, but it is undefined behavior (that is, very bad) to do so.
 
?

=?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=

Larry Smith wrote:

[...]
Actually, I don't understand what his issue is. There's nothing wrong
with the code he posted (he's not passing temporaries).

Thank you all for your responses. After reading the above comment, I
decided to try the code with other compilers --something which I should
have done before posting in the first place-- only to see no warning
about temporaries being used on that call.

The other compiler in question is GCC 3.3.1 and its diagnostic led me to
the source of the problem. Contrary to the code shown in my initial
message, the actual one had a type mismatch between the variables
declared and the arguments expected by the function. The variables were
declared as /long/ while the function expected non-const references to
/unsigned long/.

Here is what GCC had to say about it:

teste.cpp:14: error: could not convert `a' to `long unsigned int&'
blowfish.h:7: error: in passing argument 1 of `void Blowfish::cifra(long
unsigned int&, long unsigned int&)'

And here is the misleading warning produced by BCC:

Warning W8030 teste.cpp 14: Temporary used for parameter 'xa' in call to
'cifra(unsigned long &,unsigned long &)' in function main(int,char * *)

Fixing the variables declarations to make them match the type of the
references expected by the function made both compilers accept the code.

Regards,
 
C

Cy Edmunds

Ney André de Mello Zunion said:
Hello.

Binding a temporary to a non-const reference is illegal. Everybody
should be tired of hearing that. So should I. But then I found myself
wondering about a small piece of code I was writing:

void cipher(unsigned long& xa, unsigned long& xb)
{
// ...
xa = // ...
xb = // ...
}

int main()
{
unsigned long a = 1111111;
unsigned long b = 2222222;
cipher(a, b);
}

The function cipher() is supposed to transform the two /long/ arguments
received. It might have had its arguments in the form of pointers, but
the author chose to allow users to use a simple, uncluttered cipher(a,
b) call. It might also have been made to return an object containing the
two ciphered values instead.

Which of the two alternatives aforementioned do you think is better? Is
there any other one I have overlooked?

Thank you,

I think the signature

SomeClass cipher(unsigned long, unsigned long);

is clearer. Your version is ambiguous because it is not clear if xa and xb
need to be initialized before the call.
 
W

wogston

Undefined behavior, but it is not ill-formed. That is, the compiler is
not obligated
to detect and issue a diagnostic if you return a reference to an object that is about
to go out of scope, but it is undefined behavior (that is, very bad) to do
so.

It was a rhetoric question, but thanks anyway. ;-)
 
R

Ron Natalie

Actually, I don't understand what his issue is. There's nothing wrong
with the code he posted (he's not passing temporaries).
Yes, he is. Since the types don't match, but are convertable, a temporary
converted value is generated.
 
L

Larry Smith

Actually, I don't understand what his issue is. There's nothing wrong
Yes, he is. Since the types don't match, but are convertable, a temporary
converted value is generated.

There's no type mismatch in his original post.
 
?

=?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=

Ron said:
Yes, he is. Since the types don't match, but are convertable, a temporary
converted value is generated.

There seems to be something wrong anyway: BCC managed to make the type
conversion from long to unsigned long, but then complained about
temporaries being passed, while saying nothing about the automatic
conversion itself. GCC, on the other hand, refused to do the type
conversion and failed to compile.

I am not sure about what the proper behavior should be, but I would hope
that, in a situation like that, the compilers would *warn* both about
the type conversion (since there is a good chance of it being unwanted)
and the creation of temporaries. That way, a user could have a better
idea of where he went wrong.

Regards,
 
R

Ron Natalie

Ney André de Mello Zunino said:
There seems to be something wrong anyway: BCC managed to make the type
conversion from long to unsigned long, but then complained about
temporaries being passed, while saying nothing about the automatic
conversion itself. GCC, on the other hand, refused to do the type
conversion and failed to compile.
Either way is fine. The standard doesn't say anything about the message
issued for ill-formed programs, just that one should be issued. Actually
both errors are fine. It's not clear to the compiler (or even me) which is
the real error here. It could either be that you didn't intend a conversion
here (mismatched args) or you are trying to bind the converted temporary
to an non-const reference.
 

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

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top