|
-
October 31st, 2002, 02:13 PM
#1
Default Initialization of reference variables in methods
How do I initialize references in my method
BOOL GetSelectedItem(INDEX_DATA& pIndex,
int& nSelItem =-1/*???*/);
Is it possible. I know I am doing wrong, because Compiler tells
-
October 31st, 2002, 05:15 PM
#2
Code:
void foo( const int& a_i = -1 )
{
//...
}
I hope it helps.
Regards,
ZDF
What is good is twice as good if it's simple.
"Make it simple" is a complex task.
-
October 31st, 2002, 05:34 PM
#3
Well, yes that works, but obviously you won't be able to change a_i, which might defeat the point of passing by reference.
But there is no solution to this (as far as I can imagine), since the reference operator implies that you are actually passing a dereferenced pointer to an int. This means that a_i has to be somewhere in memory as opposed to a constant like -1.
The reason it works with const int& a_i = -1 is that the compiler will allocate a static variable for -1 and &a_i will point to that one. So it's the same as writing :
Code:
const static minusone = -1;
void foo(const int &i = minusone)
{
// code
}
Last edited by Yves M; October 31st, 2002 at 05:36 PM.
-
November 1st, 2002, 04:32 AM
#4
Originally posted by Yves M
Well, yes that works, but obviously you won't be able to change a_i, which might defeat the point of passing by reference.
But there is no solution to this (as far as I can imagine), since the reference operator implies that you are actually passing a dereferenced pointer to an int. This means that a_i has to be somewhere in memory as opposed to a constant like -1.
The reason it works with const int& a_i = -1 is that the compiler will allocate a static variable for -1 and &a_i will point to that one. So it's the same as writing :
Code:
const static minusone = -1;
void foo(const int &i = minusone)
{
// code
}
The reason for passing reference in such case is to eliminate the need to write a copy constructor (if that needs to be). The const keyword is to tell the user of your function that the object he passed, wouldn't get modifed.
-
November 1st, 2002, 07:05 AM
#5
Yes, I know I was referring to the line of code agni gave :
BOOL GetSelectedItem(INDEX_DATA& pIndex, int& nSelItem =-1);
If he didn't want to modify nSelItem then it would be easier to pass by value rather than try this default initialisation.
-
November 1st, 2002, 08:20 AM
#6
Re: Default Initialization of reference variables in methods
Originally posted by agni256
BOOL GetSelectedItem(INDEX_DATA& pIndex,
int& nSelItem =-1/*???*/);
Besides the problem itself just a note...why do you want to pass a reference to a POD, in this case an integer...
There is no advantage of passing POD's by reference rather than by value. I mean if the above function is just a sample to show the problem it is okay but if this is really what you are looking for than I would just answer...
Code:
BOOL GetSelectedItem(INDEX_DATA& pIndex, int nSelItem =-1);
-
November 1st, 2002, 08:36 AM
#7
Well, one use of passing by reference is to allow the function to modify the variable passed (so that the changes are reflected in the caller's scope) and make it clear that that variable is not optional. If you passed by pointer, the caller could always pass NULL and that might not make sense.
For the original question, it does not work either when you are passing a pointer to a variable, unless you specify NULL or make it a pointer to a global variable.
For example, this works:
Code:
int minusone;
void func(int *p = &minusone)
{
int i;
i = *p;
}
int main(int argc, char* argv[])
{
minusone = -1;
func();
return 0;
}
But of course this can be a source of endless errors, especially if you modify *p inside func.
Get this small utility to do basic syntax highlighting in vBulletin forums (like Codeguru) easily.
Supports C++ and VB out of the box, but can be configured for other languages.
-
November 1st, 2002, 09:27 AM
#8
Yes, you can use a global as the default parameter. The problem with that is if the parameter ever changes, you could easily get different behaviors with different, even consecutive, calls to the method. This could bugs that would be difficult to find.
Edit: Which is, umm, what Yves just said.
Jeff
Last edited by jfaust; November 1st, 2002 at 09:31 AM.
-
November 1st, 2002, 09:43 AM
#9
Originally posted by Yves M
Well, one use of passing by reference is to allow the function to modify the variable passed (so that the changes are reflected in the caller's scope) and make it clear that that variable is not optional.
Well...yes you are right. I think I did not have enough coffee yet... I usually use references only if the function does not change it thus I just const-references...
I think I got so used to it, that I did not think enough...sorry about that...
-
November 1st, 2002, 09:54 AM
#10
Passing by reference to allow changing the variable is a pretty thorny issue anyways. Here is what Stroustrup says about it (section 5.5 p99).
A reference can be used to specify a function argument so that the function can change the value of an object passed to it. For example:
Code:
void increment(int &aa) {aa++;}
void f()
{
int x = 1;
increment(x); // x = 2
}
...
To keep a program readable, it is often best to avoid functions that modify their arguments.
Get this small utility to do basic syntax highlighting in vBulletin forums (like Codeguru) easily.
Supports C++ and VB out of the box, but can be configured for other languages.
-
November 1st, 2002, 11:11 AM
#11
Originally posted by Yves M
To keep a program readable, it is often best to avoid functions that modify their arguments.
Well...basically that is the reason why I pass pointers while functions modify their arguments and const-references otherwise...
-
November 1st, 2002, 11:24 AM
#12
Possibly of interest:
Parameters are often passed in as output parameters when the method needs to set more than one value. However, it is possible for methods to return multiple values. The quick answer is to use a struct, but there are better ways in which you don't have to declare a new struct. std::pair works great for returning two values, possibly the value you are interested in as well as an error condition. For more than two values, there is boost::tuple, which can be found at boost.
For arguments that are both input and output, well... ich.
Jeff
-
November 1st, 2002, 11:45 AM
#13
Yeah, well, I do use non-const references for functions with descriptive names, like KeyPlusPlus(KeyType &key) for example. But it's true that it should generally be avoided since it's not clear to the caller that his parameter can be modified and that he can't pass a constant :/
As for multiple return values... Hum... I would still prefer using non-const references, but then I'll document the function well.
-
November 1st, 2002, 11:57 AM
#14
I would still prefer using non-const references, but then I'll document the function well.
I understand. It's a pretty big change from standard practice. However, after adjusting to it, all intentions are clear without extra documentation. I prefer policies that can be enforced by the compiler rather than relying on source documentation.
Jeff
-
November 1st, 2002, 02:22 PM
#15
I generally use references if I need to pass back multiple results.
I restrict the return value to BOOL to know whether method was successful.
In the following code:
BOOL DisplayField(int nRow=0, int nCol=0, CString strType="C",
CString strValue="", CString& strDispValue=CString(""),
I could intialize and change the value of stDispValue.
Yves may be correct here that complier needs some memory
to point to.
Can we say then its only primitives that may not work?
Intializing with Objects will, as they have memory to point to..
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|