Default reference variables

J

jryden

I can do this:

struct myInt
{
int i;
};
void func1(myInt &i = myInt());

but not this:

void func2(int &i = int());

Generates error C2440: 'default argument' : cannot convert from 'int'
to 'int &' (Visual C++ compiler)

Can someone explain why? I would like a default reference parameter
using a simple type.

Thanks,
James
 
V

Victor Bazarov

jryden said:
I can do this:

struct myInt
{
int i;
};
void func1(myInt &i = myInt());

No, you can't. A reference to non-const object (sometimes referred to
as "a const reference") cannot be bound to a temporary.
but not this:

void func2(int &i = int());

Generates error C2440: 'default argument' : cannot convert from 'int'
to 'int &' (Visual C++ compiler)

Can someone explain why? I would like a default reference parameter
using a simple type.

Do you have to have it non-const? What for?

V
 
G

Greg

jryden said:
I can do this:

struct myInt
{
int i;
};
void func1(myInt &i = myInt());

but not this:

void func2(int &i = int());

The parameter reference needs to be declared const in order to pass a
temporary:

void func2(const int& = int())

The assumption is that the program is calling func2() in order to
obtain the value it returns through the non-const parameter. So if the
program just throws that value away, why is it calling func2() in the
first place? Or, why isn't func2()'s parameter const?

Greg
 
P

Puppet_Sock

jryden wrote:
[snip]
Can someone explain why? I would like a default reference parameter
using a simple type.

Urm. Why do you want to default an argument that is a reference?
I'd expect that if you called a function without an argument, and it
wanted a reference, that this would be an error. I'm presuming that
the reason to pass a reference is so that the function can change
the value of the calling code's variable. If you only want the value
to be passed down, and not access to it, at least for a simple type,
why pass a reference?

Also, what's wrong with overloading with a version of the func that
has no arguments?
Socks
 
J

jryden

Victor said:
No, you can't. A reference to non-const object (sometimes referred to
as "a const reference") cannot be bound to a temporary.

Perhaps I should rephrase this to "my compiler allows me to do this".
In any case it does what I intend it to do...(Microsoft C++?)
Do you have to have it non-const? What for?

My intention is to have a return variable, therefore, non-const (an
[out] parameter) but I'd like the parameter to have a default value.
This is so that the hundreds of other calls to this function in my code
base don't need to be modified to pass this value as a parameter if
they don't care about what it returns.

This is typically done by doing the following:
void func3(int *i = NULL)
{
if (i = NULL) *i = x;
}

This is a constuction is don't like especially if there are many places
in the function where we would like to set the value of i.

Is there a better way to accomplish the this?
 
A

Alf P. Steinbach

* jryden:
I can do this:

struct myInt
{
int i;
};
void func1(myInt &i = myInt());

As Victor already wrote, no you can't.

Adding to that, some compilers allow you to do that as a non-standard
extension.

If your compiler is one such, then it's a good idea to turn off that
language extension, if possible.

but not this:

void func2(int &i = int());

Generates error C2440: 'default argument' : cannot convert from 'int'
to 'int &' (Visual C++ compiler)
Right.


Can someone explain why?

Stroustrup's original explanation for why an alias for (reference to) a
non-const can't be bound to an rvalue, is that that could easily lead to
surprising results like apparently modifying the value of 42 -- while
in reality of course just modifying the temporary. I seem to recall
that Pete Becker once posted a much more forceful argument in this
group, involving function arguments and overloading. Something like
calling with an int argument for a formal unsigned& -- I can't recall
-- but now that I've mentioned it, you would not want this

void doTheThing( unsigned& x ) { x = 666; }

int main()
{
int nastyValue;
doTheThing( nastyValue );
std::cout << nastyValue << std::endl;
}

to be accepted, much less produce garbage output.

I would like a default [presumably non-const] reference parameter using
a simple type.

You can do

void func2( int& i ) { ... }
void func2() { int i = 0; func2( i ); }

or you can do

int defaultI = 0;

void func2( int& i = ::defaultI ) { ... }

or whatever.
 
H

Howard

My intention is to have a return variable, therefore, non-const (an
[out] parameter) but I'd like the parameter to have a default value.
This is so that the hundreds of other calls to this function in my code
base don't need to be modified to pass this value as a parameter if
they don't care about what it returns.

This is typically done by doing the following:
void func3(int *i = NULL)
{
if (i = NULL) *i = x;

that should be
if (i == NULL)

Some people prefer
if (NULL == i)

That way, if you use = accidently, the compiler will complain, since you
can't assign to NULL.
}

This is a constuction is don't like especially if there are many places
in the function where we would like to set the value of i.

Is there a better way to accomplish the this?

I've done this some times:

void f( int* pInt )
{
int temp;
if (!pInt)
pInt = &temp;
...
*pInt = whatever;
...
*pInt = whateverelse;
...
}

That lets me do the NULL check just once at the top of the function, and
keep the code below clean.

-Howard
 
J

jryden

My intention is to have a return variable, therefore, non-const (an
[out] parameter) but I'd like the parameter to have a default value.
This is so that the hundreds of other calls to this function in my code
base don't need to be modified to pass this value as a parameter if
they don't care about what it returns.
This is typically done by doing the following:
void func3(int *i = NULL)
{
if (i = NULL) *i = x;that should be
if (i == NULL)

Some people prefer
if (NULL == i)

That way, if you use = accidently, the compiler will complain, since you
can't assign to NULL.
This is a constuction is don't like especially if there are many places
in the function where we would like to set the value of i.
Is there a better way to accomplish the this?I've done this some times:

void f( int* pInt )
{
int temp;
if (!pInt)
pInt = &temp;
...
*pInt = whatever;
...
*pInt = whateverelse;
...

}That lets me do the NULL check just once at the top of the function, and
keep the code below clean.

-Howard

Okay, I think I have a couple of more standard solutions now. Thanks
for the info.
 
D

David Harmon

On Fri, 10 Nov 2006 10:37:36 -0500 in comp.lang.c++, "Victor Bazarov"
No, you can't. A reference to non-const object (sometimes referred to
as "a const reference") cannot be bound to a temporary.

It's OK if myInt() returns a reference.
 
A

Andrey Tarasevich

David said:
It's OK if myInt() returns a reference.

:) Great idea! I wonder, however, if it is possible to come up with a correct
set of declarations in order to turn the OP's declaration into a valid one. This
is close

struct myInt {};
myInt& myInt();

void foo(struct myInt& i = myInt())
{
}

but if I remove the 'struct' from the parameter declaration Comeau will complain
with

"ComeauTest.c", line 5: error: incomplete type is not allowed
void foo(myInt& i = myInt())
^
"ComeauTest.c", line 5: error: identifier "i" is undefined
void foo(myInt& i = myInt())
^
 
B

Bo Persson

jryden said:
Perhaps I should rephrase this to "my compiler allows me to do
this". In any case it does what I intend it to do...(Microsoft C++?)

That's because you use a compiler specific language extension. If you try it
with a /Za compiler option, it will not compile.


Bo Persson
 
D

David Harmon

It's OK if myInt() returns a reference.

:) Great idea! I wonder, however, if it is possible to come up with a correct
set of declarations in order to turn the OP's declaration into a valid one. [/QUOTE]

Ouch; I failed to notice that myInt is also the type.
I was thinking more in the line of a singleton of type int.
myInt ... rather bad type name I think.
 
J

jryden

with a /Za compiler option, it will not compile.

....Neither will many other windows specific core files (specifically
ATL). Interestingly microsoft documentation explains that /Ze,
although deprecated, is also the default setting. I'll have to leave
it on for now but if and when we decide to port our code to another
platform we might have some interesting problems...but this is off
topic now.
 
J

jryden

On Fri, 10 Nov 2006 11:09:20 -0800 in comp.lang.c++, Andrey Tarasevich
I failed to notice that myInt is also the type.
I was thinking more in the line of a singleton of type int.
myInt ... rather bad type name I think.

I have lost the train of this thread, I think. myInt was just a quick
example struct from the original post (perhaps it should be MyInt)
anyway, I have been conviced that function overloading is better way to
accomplish my goal and I have changed my code accordingly.
 
A

Andrey Tarasevich

David said:
Ouch; I failed to notice that myInt is also the type.
I was thinking more in the line of a singleton of type int.
myInt ... rather bad type name I think.

Yet it can be done :) I just had an idea

struct myInt {};
myInt& bar();
#define myInt() bar()

void foo(myInt& i = myInt())
{
}
 
P

programmer

"jryden дµÀ£º
"
I can do this:

struct myInt
{
int i;
};
void func1(myInt &i = myInt());

but not this:

void func2(int &i = int());
I think a reference is just a symbol.This symbol is just occur in our
code.When call such function that take references as arguments, they
will be replaced with the actual addresses of parameters which you
reference to.When you dasm your program you will find out how it
work.You can just using this
voi func2(int &i = *(new int))
Thus,it enable i to reference to a address that store a int.
 
P

programmer

"programmer дµÀ£º
"
"jryden дµÀ£º
"
I think a reference is just a symbol.This symbol is just occur in our
code.When call such function that take references as arguments, they
will be replaced with the actual addresses of parameters which you
reference to.When you dasm your program you will find out how it
work.You can just using this
voi func2(int &i = *(new int))
Thus,it enable i to reference to a address that store a int.
I'm sorry.I have made a big problem.Never try to use this.It has a
problem with how you release your memory allocated by new.It just tell
you how reference works.
 

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
473,787
Messages
2,569,627
Members
45,328
Latest member
66Teonna9

Latest Threads

Top