pass by ref vs pass by pointer

R

Radde

HI all,

Whats the difference b/w pass by ref and pass by pointer in C++ when
ur passing objects as args..

Cheers..
 
V

Victor Bazarov

Radde said:
Whats the difference b/w pass by ref and pass by pointer in C++ when
ur passing objects as args..

A reference always refers to a valid object, according to language rules.
The difference is that when inside a function, if the argument is a ref,
you can rely upon it being a real object. If it's a pointer, it can have
an invalid value or be null.

V
 
E

E. Robert Tisdale

Victor said:
A reference always refers to a valid object, according to language rules.
The difference is that, when inside a function, if the argument is a reference,
you can rely upon it being a real object.
> cat main.cc
#include <iostream>

void f(const int& r) {
std::cout << "r = " << r << std::endl;
}

int main(int argc, char* argv[]) {

int* p = 0;
int& r = *p;
f(r);

return 0;
}
> g++ -Wall -ansi -pedantic -o main main.cc
> ./main
Segmentation fault (core dumped)
 
V

Victor Bazarov

E. Robert Tisdale said:
Victor said:
A reference always refers to a valid object, according to language rules.
The difference is that, when inside a function, if the argument is a
reference,
you can rely upon it being a real object.
[...example invoking undefined behaviour removed...]

We're are talking valid programs with defined behaviour here.
 
F

Frank Chang

NULL references are unbelievably easy in C++...

So, you can't always rely on the fact that if an argument is a
reference that it msut be a real object.

Please see the link:

http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=63717

This link provides the follwing example:

function Test(const SomeClass& param)
{
param.Method();
}

someClass* instance = SomeOperation();
Test(*instance );

--/ snip /--

If SomeOperation returns a NULL pointer than the reference in the Test
method will be null. This is very common. Of course, this doesn't
apply to references which are not function arguments.

Almost Anonymous
Wednesday, August 13, 2003
 
E

E. Robert Tisdale

Apparently, a vacuous statement.
according to language rules.
The difference is that, when inside a function,
if the argument is a reference,
you can rely upon it being a real object.

[...example invoking undefined behavior removed...]

We're are talking valid programs with defined behavior here.
 
R

Rolf Magnus

E. Robert Tisdale said:
cat main.cc
#include <iostream>

void f(const int& r) {
std::cout << "r = " << r << std::endl;
}

int main(int argc, char* argv[]) {

int* p = 0;
int& r = *p;

At this point, you enter the realm of undefined behavior. Everything
afterwards is not covered by the C++ standard anymore. Anything can happen.
Note that the behavior is already undefined _before_ f() is called.
So your program is not a valid example for passing a "null reference" to a
function.
 
F

Frank Chang

Rolf, But in this code snippet from my earlier post on null references,

If the someClass pointer, instance, is NULL, then the argument passed
by reference to Test will technically a null reference. The argument
passed to Test, *instance , is not evaluated until the function
references the argument inside the function body.
 
J

Jojo

Victor said:
A reference always refers to a valid object, according to language rules.
The difference is that when inside a function, if the argument is a ref,
you can rely upon it being a real object. If it's a pointer, it can have
an invalid value or be null.

V

void foo(Object& obj)
{
// ... do something to obj
}

int main()
{
Object* o = 0;

foo(*o);

return 0;
}

Oops, seg-fault...

Any time you deal with pointers you can have invalid objects and it's
almost impossible to not deal with pointers at some point.

Jo
 
V

Victor Bazarov

Jojo said:
void foo(Object& obj)
{
// ... do something to obj
}

int main()
{
Object* o = 0;

foo(*o);

return 0;
}

Oops, seg-fault...

Not on my system? Your program has undefined behaviour that exhibits
itself as a "seg-fault" on your system. On my system no "seg-fault"
happens, but the behaviour of your program is still _undefined_. That
means that the program cannot be governed by the rules of C++ language.
That by inference, says that according to the rules of C++ language there
can be no null references in a valid program.
Any time you deal with pointers you can have invalid objects and it's
almost impossible to not deal with pointers at some point.

I am not sure what to make of this comment of yours. Are you just
repeating what I said about pointers?

V
 
J

Jojo

Victor said:
Not on my system? Your program has undefined behaviour that exhibits
itself as a "seg-fault" on your system. On my system no "seg-fault"
happens, but the behaviour of your program is still _undefined_. That
means that the program cannot be governed by the rules of C++ language.
That by inference, says that according to the rules of C++ language there
can be no null references in a valid program.

It doesn't have to be NULL to crash. It could point to delete'd memory,
it could just point to an uninitialized object.

"Valid" program doesn't make any sense. If everyone wrote 100% perfect
"valid" code then nothing would ever crash and we would all be running
perfect software. Never happens and is the reason why people invent
"safe" languages like Java et al. For this reason references do not
make your code inherently safer (or even better) as you implied.
I am not sure what to make of this comment of yours. Are you just
repeating what I said about pointers?

V

Yes and I'm adding that it's impossible not to deal with pointers.

Jo
 
A

AndyRB

Frank said:
Rolf, But in this code snippet from my earlier post on null references,


If the someClass pointer, instance, is NULL, then the argument passed
by reference to Test will technically a null reference. The argument
passed to Test, *instance , is not evaluated until the function
references the argument inside the function body.

Not according to the c++ standard (1.8.18):
"When calling a function (whether or not the function is inline), there
is a sequence point after the evaluation
of all function arguments (if any) which takes place before execution
of any expressions or statements in
the function body"

So you don't technically have a "null reference" you have undefined
behaviour when you dereference the instance pointer and before the
function is actually called.
 
A

AndyRB

Frank said:
NULL references are unbelievably easy in C++...

No, it is unbelievably easy to invoke undefined behaviour in c++, if
you choose to do so. The undefined behaviour occurs before any "null
reference".
 
V

Victor Bazarov

Jojo said:
It doesn't have to be NULL to crash. It could point to delete'd memory,
it could just point to an uninitialized object.

Yes, IOW, invalid.
"Valid" program doesn't make any sense.

Really? Makes no sense to you, eh? Strange. The entire C++ language
Standard is written that describes valid programs. If there were no
valid programs, or the concept would make no sense, we'd have no language
Standard. Yet we do. Everybody involved in it probably is out of their
mind.
> If everyone wrote 100% perfect
"valid" code then nothing would ever crash and we would all be running
perfect software.

No. There are other errors. Like overflow. Division by zero. Absence
of a file when you try opening it. And so on, without end. And those
situations need to be dealt with _after_ the program that deals with them
is made _valid_.

Yes, a valid program shouldn't "crash". And I bet there are programs that
just do not crash. They report critical situations, work their way out of
them, and so on.
> Never happens and is the reason why people invent
"safe" languages like Java et al.

No trolling here, please.
> For this reason references do not
make your code inherently safer (or even better) as you implied.

Yes, they do. If I never write any pointer-based code (which is possible)
and instead rely on the libraries supplied with the compiler to do it
correctly, I needn't worry about problems with references. My code is
safe as long as I don't hang onto references that can become invalid.
Yes and I'm adding that it's impossible not to deal with pointers.

I do not agree.
---------------------------
#include <iostream>

int main() {
std::cout << "Hello world" << std::endl;
}
 
A

AndyRB

Jojo said:
It doesn't have to be NULL to crash. It could point to delete'd memory,
it could just point to an uninitialized object.

"Valid" program doesn't make any sense.
If everyone wrote 100% perfect
"valid" code then nothing would ever crash and we would all be running
perfect software. Never happens and is the reason why people invent
"safe" languages like Java et al. For this reason references do not
make your code inherently safer (or even better) as you implied.

But it does change when such an error may occur and therefore where the
responsibility for ensuring you have a valid object lies:

foo(SomeObj & a)
{
a.func();
}

bar(SomeObj * a)
{
a->func();
}

int main()
{
SomeObj * a;
foo(*a);
bar(a);
}

In the above the undefined behaviour is invoked for foo in the calling
code, for bar the undefined behaviour is in it's function body at the
member function call, a->func(). Even if bar checks that the pointer is
not null, it cannot guarantee that the pointer is valid.

Passing by reference puts the onus on the calling code to ensure that
any dereferenced pointer was pointing to a valid object.
 
R

Rolf Magnus

Victor said:
Yes, a valid program shouldn't "crash". And I bet there are programs that
just do not crash. They report critical situations, work their way out of
them, and so on.


No trolling here, please.

I don't see why this would be trolling. One reason why Java was created is
that it should be more robust against programming errors. Things that lead
to undefined behavior in C++ are either not possible at all in Java or lead
to a defined error (like an exception). That does not mean that Java is
"better" than C++, just that it was created with different objectives in
mind.
I do not agree.
---------------------------
#include <iostream>

int main() {
std::cout << "Hello world" << std::endl;
}

Actually, there are pointers. "Hello world" is converted to a pointer to
const char before it's passed to operator<<. And with std::endl, you pass a
pointer to a function to the second operator<<.
Your code doesn't have variables of pointer types, but it sure uses values
of such types.
 
V

Victor Bazarov

Rolf said:
Victor Bazarov wrote:

Yes, a valid program shouldn't "crash". And I bet there are programs that
just do not crash. They report critical situations, work their way out of
them, and so on.



No trolling here, please.


I don't see why this would be trolling. One reason why Java [...]

That's what I call trolling. Java is OFF-f#@*ng-TOPIC, yet you just
continued a discussion on it. He successfully trolled you into this.
Actually, there are pointers. "Hello world" is converted to a pointer to
const char before it's passed to operator<<. And with std::endl, you pass a
pointer to a function to the second operator<<.

So what? I haven't explicitly declared/defined/initialised/assigned or
dereferenced a pointer in that program. It's all done by the language
itself or by the library.
Your code doesn't have variables of pointer types, but it sure uses values
of such types.

And the library is just full of them. Doesn't mean shit.

OK, here you go

#include <iostream>

int main() {
std::cout << 'H' << 'e' << 'l' << 'l' << 'o'
<< ' ' << 'w' << 'o' << 'r' << 'l' << 'd' << '\n';
}

Better now?

V
 
F

Frank Chang

Andy, I know what the c++ standard says about the fact that that all
evaluation of function arguments takes place before execution of any
expressions of any expressions or statements in the the function body.
This is very similar to way the Scheme interpreter evaluator
functions(see Structure and Interpretaion of Computer Program by Harold
Abelson and Gerald Sussman). But as "almost anonymous" says, what the
C++ standard and the C++ compiler do are actually two different things.


"The failure occurs inside the TestFunction and not at the call to
TestFunction. This is with the Metrowerks compiler but I'm sure it's
true for all compilers.

The dereference does not occur at the call site because it's not
deferenced at the point. Instead, because it's a reference parameter,
the address is pushed onto the stack.

If the parameter was not a reference parameter then you would be
right... the dereference would occur at the call."

So, in reality , the argument addresses are pushed on the stack without
being deferenced. I guess the best way to resolve our difference is to
look at assembly code that the C++ compiler generates.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top