default value with reference variable

S

sam

Hi,

I m wondering why I can't declare reference variable for default value
in a function argument variable?

eg.

class A
{
void f(string &str="");
};

This causes compiled time error.

Sam.
 
A

Achintya

sam said:
Hi,

I m wondering why I can't declare reference variable for default value
in a function argument variable?

eg.

class A
{
void f(string &str="");
};

This causes compiled time error.

Sam.

Hi,

You cannot declare a non-const reference to non-lvalue. The "string"
that you are tring to declare doesn't have a l-value for the reference
to get associated with. Hence...

void f(const string& str="");

will work fine in VC++ 6.0

-vs_p...
 
S

sam

Achintya said:
Hi,

You cannot declare a non-const reference to non-lvalue. The "string"
that you are tring to declare doesn't have a l-value for the reference
to get associated with. Hence...

void f(const string& str="");
Sorry, I m a bit confused with this. Why const string& works and string&
doesn't?

Sam.
 
A

Achintya

sam said:
Sorry, I m a bit confused with this. Why const string& works and string&

Yup...C++ compilers have two type of 'types' associated with C++
variables and constants. The two types are l-value and r-value. l-value
is associated with variables and r-value is associated with constants.
For ex:

a = 5; // is ok! but because 'a' is a variable and has a associated
'l'ocation in memory hence it has l-value.
5 = a; // is not OK because '5' is a numerical 'const' and doesn't have
a l-value associated with it but it has a r-value

.....and now in your situation the "" string is a const. hence that
cannot be done.

(For more explanation on l-value and r-value look:
http://cplus.about.com/od/cprogrammin1/l/bldef_lvalue.htm)

-vs_p...
 
B

ben

Reference is supposed to be another name of an object. In order for that
object to have a name it must be an "l-value". So what is l-value? Well, in
the statement below:

int phone_number = 21223345;
string my_address = get_my_new_address("my name is ben");

phone_number and my_address are an l-values (left values); 21223345 and
get_my_new_address("my name is ben") are r-values (right values). A variable
can be bound to either an l-value or an r-value. But as with references,
they can only be bound to an l-value. Why? Simply think that an r-value
doesn't have a name. Consider:

int num = 2;
int& ref_to_num = number; // OK, now ref_to_num is just another name of
num

int& ref_to_oops = 2; // Error, ref_to_oops is just another name
of...er...em...nothing! It can't be done!
ref_to_num = 2; // OK, same as num = 2;

why must have a name? Consider:

fruit& apple = fruit();

Well, if the above example works, then apple will reference to a temporary
object fruit(), which will be destroyed at the end of the statement. And the
subsequent use of apple will be catastrophic!

So a workaround of what you want to do might be:

class A
{
static string default_str;
void f(string& str = default_str); // default_str is an l-value
};

string A::default_str = "";


Regards,
Ben
 
M

Mark P

ben said:
why must have a name? Consider:

fruit& apple = fruit();

Well, if the above example works, then apple will reference to a temporary
object fruit(), which will be destroyed at the end of the statement. And the
subsequent use of apple will be catastrophic!

Helpful explanation. But I thought a reference bound to a temporary
causes the lifetime of the temporary to extend to the lifetime of the
reference?
 
R

Ron Natalie

Mark said:
Helpful explanation. But I thought a reference bound to a temporary
causes the lifetime of the temporary to extend to the lifetime of the
reference?

Yes, but you can only bind a rvalue to a const reference.
The above is invalid.
const fruit& = fruit();
 
B

ben

Helpful explanation. But I thought a reference bound to a temporary
causes the lifetime of the temporary to extend to the lifetime of the
reference?

It is a good idea. Indeed it is what is happening with heap-allocated
objects:

int ref_to_num = *(new int); // heap allocation
ref_to_num = 1; // OK
delete &ref_to_num; // End the life of object referenced by
ref_to_num
ref_to_num = 2; // undefined behavior, probably a crash

But with local (stack allocated) variables, things are a little different.
Object construction and destruction is always affiliated with stack
management. So we have

Fact 1. Temporary object must be popped from the stack.
Fact 2. If an object is popped, it must be properly destroyed (by
calling the destructor).

Consequently, a temporary object must be destroyed before the next
statement. If you want to explicitly management the object's lifetime with a
reference, heap allocate the object.

Regards
Ben
 
B

ben

class A
{
void f(string &str="");
};

Apart from my previous comments, the absence of const implies that the
function is gonna change the content of str. But if so a default value
doesn't make sense at all (making change to default value??) This is the
beauty of C++: if you design something seriously wrong, you get a compiler
error :)

Exactly what do you want to achieve with that code?

Ben
 
A

Alan Johnson

ben said:
Consequently, a temporary object must be destroyed before the next
statement.

This is not correct. The compiler must guarantee that temporaries bound
to a const reference exist for the lifetime of the reference.
 
O

Old Wolf

ben said:
It is a good idea. Indeed it is what is happening with
heap-allocated objects:

int ref_to_num = *(new int); // heap allocation
ref_to_num = 1; // OK
delete &ref_to_num; // End the life of object referenced by

Undefined behaviour -- ref_to_num is an automatic int,
you copied the value of it from the int created with (new int)
which has now been leaked.
ref_to_num = 2; // undefined behavior, probably a crash

Fine, actually.

Also, this example (even if you modified it to: int &ref_to_num)
has nothing to do with the original topic (extension of
lifetime of temporaries). *(new int) is not a temporary.
Fact 1. Temporary object must be popped from the stack.

There is no need for a 'stack' of any sort to be present.
So this is not really a fact.
Fact 2. If an object is popped, it must be properly destroyed (by
calling the destructor).

You mean, if an object is deallocated it must be properly
destroyed. Which goes without saying. (Note: this 'fact' is
irrelevant, as temporary objects need not be deallocated,
see 'fact 1').
Consequently, a temporary object must be destroyed before the next
statement.

That doesn't follow from anything you just said.
There would be no contradiction if temporary objects lasted
until the end of the current block, for example.
In fact, that is exactly what happens when the temporary
object gets bound to a reference.
If you want to explicitly management the object's lifetime
with a reference, heap allocate the object.

Deeper and deeper into non-sequitur territory. If you want to
manage the lifetime with a reference.... use a reference!

Heap allocation has different semantics than automatic
allocation, as you have already noted.
 

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
474,202
Messages
2,571,057
Members
47,668
Latest member
SamiraShac

Latest Threads

Top