lvalue (s) and rvalue (s)

J

jimjim

Hello,

void func( const string& ISIN) {
cout << ISIN << endl;
}

int main() {
char bufIsin[31];
char *charIsin = new char[31];
strcpy(bufIsin, "FIRST");
strcpy(charIsin, "SECOND");
func(bufIsin);
func(charIsin);
}

1. The above compiles fine. In both instances, a char * is passed to the
func( ). On the other hand, func( ) recieves a string &. What is the exact
argument passing process? (i.e is the string(char *) ctr invoked? is this
called type promotion?)

2. If the func( )'s signature is void func(string& ISIN) the code does not
compile. Can you explain to me the meaning of the error, please?
~/MyTests $CC Passing_CharBuf_Char\*_to_func_accepting_string.cc
"Passing_CharBuf_Char*_to_func_accepting_string.cc", line 21: Error: Formal
argument ISIN of type std::basic_string<char,
std::char_traits<char>, std::allocator<char>>& in call to
func(std::basic_string<char, std::char_traits<char>,
std::allocator<char>>&) requires an lvalue.
"Passing_CharBuf_Char*_to_func_accepting_string.cc", line 22: Error: Formal
argument ISIN of type std::basic_string<char, std::char_traits<char>,
std::allocator<char>>& in call to func(std::basic_string<char,
std::char_traits<char>, std::allocator<char>>&) requires an lvalue.
2 Error(s) detected.

TIA
jimjim
 
J

jimjim

P.S: what happens if the char * is not null terminated and the string(const
char *) ctr is invoked? Does string dim = "hello"; ensure that the "hello"
is terminated?
 
H

Heinz Ozwirk

jimjim said:
Hello,

void func( const string& ISIN) {
cout << ISIN << endl;
}

int main() {
char bufIsin[31];
char *charIsin = new char[31];
strcpy(bufIsin, "FIRST");
strcpy(charIsin, "SECOND");
func(bufIsin);
func(charIsin);
}

1. The above compiles fine. In both instances, a char * is passed to the
func( ). On the other hand, func( ) recieves a string &. What is the exact
argument passing process? (i.e is the string(char *) ctr invoked? is this
called type promotion?)

The type of func's parameter is "const string&", not just "string&". The compiler will generate a temporary string object, initialize it with the contents of the character array and pass a reference to the temporary object to the function.
2. If the func( )'s signature is void func(string& ISIN) the code does not
compile. Can you explain to me the meaning of the error, please?

A reference to a non-const object cannot be bound to a temporary.

HTH
Heinz
 
J

jimjim

void func( const string& ISIN) {
cout << ISIN << endl;
}

int main() {
char bufIsin[31];
char *charIsin = new char[31];
strcpy(bufIsin, "FIRST");
strcpy(charIsin, "SECOND");
func(bufIsin);
func(charIsin);
}


2. If the func( )'s signature is void func(string& ISIN) the code does not
compile. Can you explain to me the meaning of the error, please?
A reference to a non-const object cannot be bound to a temporary.

Does the compiler require a const argument because changing the state of a
temporary object is practically without any essence?

What does "func(std::basic_string<char, std::char_traits<char>,
std::allocator<char>>&) requires an **lvalue**" mean?

TIA
 
J

jimjim

The type of func's parameter is "const string&", not just "string&". The
compiler will generate a temporary string
object, initialize it with the contents of the character array and pass a
reference to the temporary object to the function.

By the way, is the temporary object created on the stack?
 
K

Kai-Uwe Bux

jimjim said:
void func( const string& ISIN) {
cout << ISIN << endl;
}

int main() {
char bufIsin[31];
char *charIsin = new char[31];
strcpy(bufIsin, "FIRST");
strcpy(charIsin, "SECOND");
func(bufIsin);
func(charIsin);
}


2. If the func( )'s signature is void func(string& ISIN) the code does
not
compile. Can you explain to me the meaning of the error, please?
A reference to a non-const object cannot be bound to a temporary.

Does the compiler require a const argument because changing the state of a
temporary object is practically without any essence?

No. The reasons for that provision are lost to history. In my opinion, it is
just a bug in the language. In my experience, it makes for much hassle
without tangible gain.

Modifying a temporary makes perfect sense: just think of a proxy class; it
undergoes some changes and at the end of its lifetime writes back the
changes to the object from which it was created. Or think of a temporary
stream object:

#include <fstream>
#include <string>
#include <iomanip>

int main ( void ) {
std::fstream ( "/dev/stdout" )
<< std::dec
<< std::string( "hello world!\n" );
}


Now, you may wonder that this compiles as the temporary is clearly modified.
The reason is that the standard does *not* prohibit calling non-const
members on temporaries. That is the reason for std::dec. In comparison, the
following does not compile:

#include <fstream>
#include <string>
#include <iomanip>

int main ( void ) {
std::fstream ( "/dev/stdout" )
<< std::string( "hello world!\n" );
}


If you can find a rational for this, please let me know.



Best

Kai-Uwe Bux

ps.: this is one of my pet peeves. So please excuse the ranting.
 
B

Bo Persson

Kai-Uwe Bux said:
No. The reasons for that provision are lost to history. In my
opinion, it is
just a bug in the language. In my experience, it makes for much
hassle
without tangible gain.

But jimjim is right on the original motivation. The C promotion rules
for built in types is the real "bug".

void inc(float& x)
{ ++x; }

int i = 0;
inc(i);

or even

inc(1.0);

What would happen here, if it was allowed? Nothing!

The parameter would be converted to a float temporary, which is then
incremented.
Modifying a temporary makes perfect sense: just think of a proxy
class; it
undergoes some changes and at the end of its lifetime writes back
the
changes to the object from which it was created. Or think of a
temporary
stream object:

#include <fstream>
#include <string>
#include <iomanip>

int main ( void ) {
std::fstream ( "/dev/stdout" )
<< std::dec
<< std::string( "hello world!\n" );
}


On the other hand, *this* is a bug in the language. :)

Bo Persson
 
K

Kai-Uwe Bux

Bo said:
But jimjim is right on the original motivation. The C promotion rules
for built in types is the real "bug".

void inc(float& x)
{ ++x; }

int i = 0;
inc(i);

or even

inc(1.0);

What would happen here, if it was allowed? Nothing!

The parameter would be converted to a float temporary, which is then
incremented.

Ok, I agree that inc(i) doing nothing might be surprising. On the other
hand, I would not want it to do the expected thing either: increment i as a
float and then truncate the result (thus overall being just unpredictable
due to rounding).

However, I wonder: is it really the initialization of a non-const reference
from a temporary that causes the problem or the implicit conversion. But I
guess, we agree on that: as you pointed out, the bug lies within the
promotion rules.


[snip]


Best

Kai-Uwe Bux
 

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,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top