Skip to main content
gamedev.net
🔒 Locked

Passing a ref to another function

Started by Nacho Dec 23, 2001 at 9:20 PM 14 replies 450+ views
Original Post
Nacho
Nacho
Hi! I´m practising my C++ for a while and I´ve got a very boring question that I hope you can answer. Imagine I´ve got a function that takes a reference to integer "int &" and returns nothing (void). I wanted to pass that number to another function that also takes a reference to integer but my compiler complains arguing that the caller function cannot convert this parameter from int to int&. Any idea? Oluseyi, are you there? =)
clabinsky
clabinsky
Making on function dependent on another seems as bad programming practice. I think you should code the two functions independently and make the following call:

main
{
int something=11;

//modify something in both f1 and f2
f1(something);
f2(something);

}
void f1(int& x)
{
...//(For an int I consider this bad programming (unless special circumstaces) - use return)
}
void f2(int& y)
{
...
}

However, a rule that I keep is that a function that modify one variable should return the value. If you modify more than one variable use reference calls. Your call would then be:

something=f2(f1(something));

Note however that some args should be sent by reference unless special circumstances.

If you want this to be done in one call make a new function out of it. This is how I would do it to keep the functions as clean as possible. Maybe someone else has another idea.

I hope this was to some help.

Why make it simple when you can make it sooo nice and complicated?
a person
a person
thats a silly rule. simply put then you have no way to return special error messages a la dx.
clabinsky
clabinsky
Haha, yes it might be silly to you. As I said, if I need to return messages (plural) I use refs. As for logging and error messages, I have a class that all others have access to.

If something happen that should not happen this will be recorded by calling the Error handler in the class, without returning the value.

Now, no rule is without exception, I usually return success or failure by my functions. As simple as that. If something bad happens, it will be recorded in the Errlog.txt by the error handler. If I need to check the message, each class could save the last error message in a string that I coud access when the class returns a failure. If I have to return a value as weel as the result of the function I could use both of course.

If I am still silly, I´d like to know why
Why make it simple when you can make it sooo nice and complicated?
clabinsky
clabinsky
Well, I agree with you. As I said under special circumstances. You would almost never pass an object by value! If you do you might get in trouble creating a local copy that will access the same memory as the passed object and as soon as the function is done the destructor of the copied object will be run...

Well, in worst case. You could avoid this easily. But when we speak about passing parameters I do not generally speak about objects because I rarely pass them and I think you should have very good reasons for passing one. Objects should almost never be passed by value, end of story.

Get into the game, I am using the rule for chars, ints, doubles, floats etc.
Why make it simple when you can make it sooo nice and complicated?
null_pointer
null_pointer
quote:
Original post by

thats a silly rule. simply put then you have no way to return special error messages a la dx.


throw std::exception();

You could also create a new exception class to provide such services as logging, translating message codes into a format to be read by the end user of the software, and so on. The main benefit is the translation of this style of coding:

bool complexfunction()
{
if( !simplefunction1() )
return false;

if( !simplefunction2() )
return false;

if( !simplefunction3() )
return false;

return true;
}


...into this...

void complexfunction()
{
simplefunction1();
simplefunction2();
simplefunction3();
}


...and separate the normal code from the error condition code. This also means that the return value is always free for returning the results of the function (if any), rather than trying to package some kind of error code, and it reduces the need to send pointer/reference parameters to return data.
Nacho
Nacho
quote:
Original post by Null and Void
Post some code. There's no reason that you can't continue to pass the reference. However, if there's more you're accidentally not telling us there's plenty of things that can be wrong .

[Resist Windows XP's Invasive Production Activation Technology!]


Ok, here´s the code. It´s in Spanish, but Numero stands for number and modificar stands for modify, so it´s easy. I got two errors from MSVC++ 6.

#include

using std::cout;
using std::endl;

void modificar(int №);
void remodificar(int №);
void reremodificar(int №);

int main()
{
int numero = 5;
modificar(numero);
cout << "Numero vale: " << numero << endl;
return 0;
}

void modificar(int №)
{
remodificar(numero<<1);
return;
}

void remodificar(int №)
{
reremodificar(numero<<1);
return;
}

void reremodificar(int №)
{
numero = numero << 1;
return;
}

--------------------Configuration: Pruebas - Win32 Debug--------------------
Compiling...
Pruebas 2.cpp
C:\Archivos de programa\Microsoft Visual Studio\MyProjects\Pruebas\Pruebas 2.cpp(20) : error C2664: 'remodificar' : cannot convert parameter 1 from 'int' to 'int &'
A reference that is not to 'const' cannot be bound to a non-lvalue
C:\Archivos de programa\Microsoft Visual Studio\MyProjects\Pruebas\Pruebas 2.cpp(26) : error C2664: 'reremodificar' : cannot convert parameter 1 from 'int' to 'int &'
A reference that is not to 'const' cannot be bound to a non-lvalue
Error executing cl.exe.

Pruebas.exe - 2 error(s), 0 warning(s)


Any idea? Thanks a lot!!



Edited by - Ignacio Liverotti on December 24, 2001 4:30:25 PM
Null and Void
Null and Void
Ah, the error is obvious now . You''re passing a value, not a variable as the reference. I''ll modify your code to what I think you wanted.
  
void modificar(int №) {
numero <<= 1;
remodificar(numero);
}
void remodificar(int №) {
numero <<= 1;
reremodificar(numero);
}
void reremodificar(int №) {
numero <<= 1;
}


[Resist Windows XP''s Invasive Production Activation Technology!]
merlin9x9
merlin9x9
The only reason references should be used as parameters is when you want to avoid stack usage, which is both show and inefficient. And they should be const references. For parameters that are "okay" to pass on the stack, pass by value. For everything else, use pointers. Here''s why:

Let''s say that we have a function, myfunc. Just looking at a call to it, can you tell whether or not the arguments (x and y) are going to be changed?

int x = 10, y = 2;
int a = myfunc(x, y);

myfunc have been define any number of ways to make the function call look like that:
int myfunc(int x, int y)
int myfunc(int& x, int& y)
int myfunc(int& x, int y)
int myfunc(int x, int& y)
etc.

Some allow the passed argument to be changed, and others not. And you just can''t tell from a call.

Now, if you followed the convention I suggested where you use pointers with any parameter that will be changed, and the rest are passed by value or const references, it becomes obvious, just from a glance:

int x = 10, y = 2;
int a = myfunc(x, &y);

It''s obvious because, in this convention, the only time we''d ever need the address of an object is when we might be interested in changing it. And if we don''t take the object''s address, then we''ll never be changing it, folling the convention.

Certainly, people argue that this is all a matter of opinion (like the int &x versus int& x argument). But even Bjarne himself suggests not to use references very often.
Nacho
Nacho
quote:
Original post by Null and Void
Ah, the error is obvious now . You''re passing a value, not a variable as the reference. I''ll modify your code to what I think you wanted.

    
void modificar(int №) {
numero <<= 1;
remodificar(numero);
}
void remodificar(int №) {
numero <<= 1;
reremodificar(numero);
}
void reremodificar(int №) {
numero <<= 1;
}


[Resist Windows XP''s Invasive Production Activation Technology!]

I just didn´t know that I was passing a value. Thanks! You helped me a lot!

merlin9x9
merlin9x9
Null and Void, that''s a very good point. Even worse, testing for NULL is never enough, since it''s fairly easy to coerce anything into a pointer to anything. On Win32, you''re better off using IsBadReadPtr and/or IsBadWritePtr over the full number of bytes as the object you''re expecting—in an assertion, most likely. But that''s cumbersome, and only really practical for non-release builds. I happen to think that readability is far more important than convenience in this case, but, of course, this is just opinion.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.