473,836 Members | 1,608 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Pass-by-reference instead of pass-by-pointer = a bad idea?

Hi!
I've been thinking about passing parameteras using references instead
of pointers in order to emphasize that the parameter must be an
object.

Exemple:
void func(Objec& object); //object must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea since , in the reference case, it's
clear that NULL is not an option. It's also clear that NULL is an
option when a pointer is expected (stating the obvious :-) ). The code
becomes somewhat more self-documenting.

Any comments on why this could be a bad idea or do you think it's just
a matter of taste?

/H
Jul 23 '05
110 9976
Why make every little routine test over and over again something that
isn't to ever happen?

The question people ask is, IMO, the wrong one.
People ask: When should I pass by reference?
The right question is "When should I pass by pointer?"

and the answer is "Whenever you want to allow a pointer-to-nothing
(i.e. 0)"
which is in my experience almost never.

I go one step further:
Pass by const reference unless the object may change.
This way when you call some code the intent is crystal clear.

I don't buy the argument that someone might then dereference a null
pointer and thus you always have to protect your code. Your interface
is a contract. At least with references you are making your intent
clear. Pass by pointer and you are saying "You're allowed to pass 0".
Too often if you rely on this in other people's code you'll be
surprised by seg faults because they did not handle being passed 0 --
they really meant it had to point to something.

You rely on other things in the contract: that the kind of object is
the kind you ask for (no static_cast downcasting to the wrong type or
your program will crash), that the relationships between objects is set
up, and so forth. For clarity of code and ease of maintainability I've
found passing by reference (const and non-const) leads to far clearer,
more maintainable and more robust code. Adding null pointer checks all
over the place instead of only in the places where the pointers can be
0 hides programmer intent while adding noise to the program and slowing
runtime. So why do it?

Stuart

Jul 23 '05 #11
Kristo wrote:
Mr A wrote:
Hi!
I've been thinking about passing parameteras using references instead
of pointers in order to emphasize that the parameter must be an
object.

Exemple:
void func(Objec& object); //object must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea since , in the reference case, it's
clear that NULL is not an option. It's also clear that NULL is an
option when a pointer is expected (stating the obvious :-) ). The code
becomes somewhat more self-documenting.

Any comments on why this could be a bad idea or do you think it's just
a matter of taste?


That looks like a very good idea to me, and IIRC, the FAQ agrees. IMHO,
it's more than a matter of style; it's also a matter of safety. If a
parameter should never be null, then don't give it the chance.

Kristo


This is one man's opinion:
http://doc.trolltech.com/qq/qq13-apis.html
Pointers or References?

Which is best for out-parameters, pointers or references?

void getHsv(int *h, int *s, int *v) const
void getHsv(int &h, int &s, int &v) const
Most C++ books recommend references whenever possible, according to the
general perception that references are "safer and nicer" than pointers. In
contrast, at Trolltech, we tend to prefer pointers because they make the
user code more readable. Compare:

color.getHsv(&h , &s, &v);
color.getHsv(h, s, v);
Only the first line makes it clear that there's a high probability that h,
s, and v will be modified by the function call.

http://en.wikipedia.org/wiki/Matthias_Ettrich
http://www.kde.org/

When I started working with the KDE, I could download it with a 28.8 modem,
build and install it in a matter of a few minutes on a Pentium. It now
occupies 1.2 G on my harddrive. That may (does) represent some bloat, but
it also represents unquestionable progress. Ettrich is a man who
understands the three principles of good software design. User interface,
user interface, and user interface.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #12
Ian
Kristo wrote:
Mr A wrote:
Hi!
I've been thinking about passing parameteras using references instead
of pointers in order to emphasize that the parameter must be an
object.

Exemple:
void func(Objec& object); //object must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea since , in the reference case, it's
clear that NULL is not an option. It's also clear that NULL is an
option when a pointer is expected (stating the obvious :-) ). The code
becomes somewhat more self-documenting.

Any comments on why this could be a bad idea or do you think it's just
a matter of taste?

That looks like a very good idea to me, and IIRC, the FAQ agrees. IMHO,
it's more than a matter of style; it's also a matter of safety. If a
parameter should never be null, then don't give it the chance.

And passing by reference does this? I don't think so.

Ian
Jul 23 '05 #13
Steven T. Hatton wrote:
John Carson wrote:
"Steven T. Hatton" <ch********@ger mania.sup> wrote in message
news:as****** **************@ speakeasy.net
In your example, you are not trying to pass null, you are trying to
pass a literal.He is passing NULL which is the same as 0.


'0', when it appears in your code, is a literal. If the reference were
const, the code /would/ compile.


In C++ NULL is zero (0).

#include <string>
std::string cfunc(const std::string& s) { return s; }
int main() {
cfunc(0);
}

It still has a problem. The above aborts when executed. That's one better
than a segfault, but not typically what I want from a program.
That results in the attempt to create a temporary
object of type int and assign it to the non-const reference. This,
however, will compile:

#include <string>
std::strin g func(std::strin g& s) { return s; }
int main() {
std::string* s(0);
func(*s);
}

Dereferenci ng a NULL pointer is undefined behaviour by section 8.3.2/4.
When I run your code, the program crashes.


Yes, it segfaults. That was my point.


#include <iostream>
#include <string>

struct Stuff
{
int a;
double b;
};

void func(const Stuff& obj)
{
obj.a = 1;
}

int main()
{
Stuff s;
Stuff *sp = 0;

func(s);
// the next 3 produce comple time errors
func(0);
func(NULL);
func(sp);
// the next one is a stupid programmer error - deref'ing a NULL
// pointer. it crashes before func() is called - a good reason
// to use ref's exclusively rather than pointers.
func(*sp);

return 0;
}
The pros & cons of refs vs pointers could be argued forever.
Advocates of the different approaches will probably never
agree. So let's not beat it to death anymore.

Regards,
Larry
Jul 23 '05 #14
Stuart MacMartin wrote:
Why make every little routine test over and over again something that
isn't to ever happen?
Not sure what you mean here. If you can ensure that the error cannot
happen, then there's no point in testing for it. OTOH, if you can't be
sure it won't happen, then you either take your chances for the sake of
performance (and should ask yourself if it really is all that costly to
make the check), or you put in an error check.
The question people ask is, IMO, the wrong one.
People ask: When should I pass by reference?
The right question is "When should I pass by pointer?"

and the answer is "Whenever you want to allow a pointer-to-nothing
(i.e. 0)"
which is in my experience almost never.
That is certainly not a universal assumption. I would never intentionally
pass a null pointer unless I had explicit information telling me it was OK.
I go one step further:
Pass by const reference unless the object may change.
This way when you call some code the intent is crystal clear.

I don't buy the argument that someone might then dereference a null
pointer and thus you always have to protect your code. Your interface
is a contract. At least with references you are making your intent
clear.
Assuming the person maintaining the code actually looks at the function
declaration, rather than just the call. It would appear (much to my
amazement) many C++ programmers believe a programmer should *not* look at
the actual source code where the interface is declared.
Pass by pointer and you are saying "You're allowed to pass 0".
Too often if you rely on this in other people's code you'll be
surprised by seg faults because they did not handle being passed 0 --
they really meant it had to point to something.
It seems to me your understanding of the implication of a pointer parameter
is unfounded. The only time I might assume it's safe to pass a null
pointer is if the parameter has a default null value.
You rely on other things in the contract: that the kind of object is
the kind you ask for (no static_cast downcasting to the wrong type or
your program will crash), that the relationships between objects is set
up, and so forth. For clarity of code and ease of maintainability I've
found passing by reference (const and non-const) leads to far clearer,
more maintainable and more robust code.
I certainly prefer the use of operator[](), operator.() on a reference or an
object over doing the same on a pointer. If you are working with a
conceptual design that uses shared objects, you are almost certainly going
to use some kind of smart pointer. You will have to dereference that
somewhere. This is why I find the proposal to overload operator.() and
operator.*() so attractive. Of course some people believe the new move
semantics will obviate all need for such things. Clearly that is not the
case.

At least with a const reference, I *might* be able to catch an exception.
With a non-const reference, a null pointer is a segfault.
Adding null pointer checks all
over the place instead of only in the places where the pointers can be
0 hides programmer intent while adding noise to the program and slowing
runtime. So why do it?


Because code that does use pointers, and proper error checking won't crash
due to a null pointer, but code that uses references to pass variables
*can* crash because of a null pointer being passed to a reference. So far
as I know, there is no way to protect yourself from that, other than
checking for null before dereferencing.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #15
Larry I Smith wrote:
Steven T. Hatton wrote:
John Carson wrote:
"Steven T. Hatton" <ch********@ger mania.sup> wrote in message
news:as***** *************** @speakeasy.net
In your example, you are not trying to pass null, you are trying to
pass a literal.
He is passing NULL which is the same as 0.
'0', when it appears in your code, is a literal. If the reference were
const, the code /would/ compile.


In C++ NULL is zero (0).


Exactly my point. It is NOT a null pointer, it is a literal.
#include <iostream>
#include <string>

struct Stuff
{
int a;
double b;
};

void func(const Stuff& obj)
{
obj.a = 1;
}

int main()
{
Stuff s;
Stuff *sp = 0;

func(s);
// the next 3 produce comple time errors
func(0);
func(NULL);
func(sp);
The error on the last example is because you are passing a pointer to a non
pointer type, and has nothing to do with the value of the type. In the
pervious examples you are passing an integer literal which is likewise
illegal.

// the next one is a stupid programmer error - deref'ing a NULL
// pointer. it crashes before func() is called - a good reason
// to use ref's exclusively rather than pointers.
func(*sp);

return 0;
}
The pros & cons of refs vs pointers could be argued forever.
Advocates of the different approaches will probably never
agree. So let's not beat it to death anymore.

Regards,
Larry


--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #16
Steven T. Hatton wrote:
John Carson wrote:
Dereferencing a NULL pointer is undefined behaviour by section
8.3.2/4. When I run your code, the program crashes.


Yes, it segfaults. That was my point.


There's no mention of segfaulting in the standard. The behaviour is
undefined. That means that anything can happen, including the function
executing without any apparent problem.

DW
Jul 23 '05 #17
Mr A wrote:
Hi!
I've been thinking about passing parameteras using references instead
of pointers in order to emphasize that the parameter must be an
object.

Exemple:
void func(Objec& object); //object must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea since , in the reference case, it's
clear that NULL is not an option. It's also clear that NULL is an
option when a pointer is expected (stating the obvious :-) ).
Not necessarily. Try passing a null pointer to ::strlen(). Just because a
pointer is passed doesn't necessarily mean that the function will permit it
to be null.
The code
becomes somewhat more self-documenting.
Yes, because you at least don't have to bother finding out if a null pointer
is acceptable.
Any comments on why this could be a bad idea or do you think it's just
a matter of taste?


One thing about the reference case is that you can't tell from the call
whether it is pass by value or pass by reference. In the pointer case it is
at least obvious from the call that an address is being passed, so you are
alerted that the function might change the object.

DW
Jul 23 '05 #18
Well I suppose most of this comes down to local convention. I prefer to
work with references, and allow a semantic difference between a
parameter passed by reference rather than passed by pointer.

Your comment:
Because code that does use pointers, and proper error checking won't
crash due to a null pointer, but code that uses references to pass
variables *can* crash because of a null pointer being passed to a
reference. So far as I know, there is no way to protect yourself from
that, other than checking for null before dereferencing.

And that's precisely the point.

I figure you should check for null before dereferencing (or otherwise
using what a pointer points to), and once you've safely dereferenced
continue to use that reference. You feel you should not trust your
caller, so insist on checking the pointer over and over again - and
instead of trusting your callers like I do, you trust the people who
write the routines you call. Since you'd check that the address of a
reference isn't 0, you see no semantic difference between passing a
pointer and a reference.

Just out of curiosity: do you do dynamic_cast of all your variables to
make sure the types are the same as the parameters you specified? This
might sound snide, but I've had people downcast or force a cast
incorrectly, with problems only showing up when the data model changes
significantly or subtly on on rare data. If you can't believe they are
passing a reference to an object when you ask for a reference, how can
you believe that they are passing the correct kind of object? It's
easy to fool the compiler into allowing this. The compiler can help
us, but only to a point. Eventually someone has to understand what a
routine is supposed to do before they call it.

Another thing that puzzles me in all of this: doesn't anyone use a
development environment? How can you not know the parameters and
whether they are passed by value or pointer or reference, const or
non-const?

Stuart

Jul 23 '05 #19
Steven T. Hatton wrote:
[]
Most C++ books recommend references whenever possible, according to the
general perception that references are "safer and nicer" than pointers. In
contrast, at Trolltech, we tend to prefer pointers because they make the
user code more readable. Compare:

color.getHsv(&h , &s, &v);
color.getHsv(h, s, v);
Only the first line makes it clear that there's a high probability that h,
s, and v will be modified by the function call.


Hm. I think if the semantics is "return value" then it should be a
return value grammatically too - i.e. return some HSV struct or
similar. If there is some strong reason to pass in a pointer/ref
and store the return value there, then I tend to agree that it's
easier to read if it's a pointer.
However in this case the name "getHsv" makes it pretty clear too
what's going to happen...

And when it's const, I'd never use a pointer if I don't have to.
If the function needs an object and cannot deal with a null
pointer/ref, then why should it check for null? If the client
passes in some value by dereferencing a pointer, then it's clearly
the clients responsibility to assure that this pointer can never
be null...
I know that dealing with non-perfect but real-life programmers
isn't easy, but I think one has to draw a line somewhere. If
a programmer isn't able to understand the simple fact that he/she
can't dereference a null pointer then he/she really shouldn't be
a programmer.

And: how do your functions handle situations where the client
passes in a null pointer for something that may not be null?
assert, abort, throw (std::invalid_a rgument, ...?)?
Jul 23 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
2084
by: winlinchu | last post by:
Hi! I use Python, and writing some extension modules I think which could be written an C compiler, useful only to compile extension modules (I not think an GCC!!!!), so that the user not have to use GCC, Microsoft Visual C++, or other. It must have an common API to all platforms, even if obviously the implementation is various. Could be write in 100% Python pure.
29
1970
by: Jim Hubbard | last post by:
Yet another hotfix alert (http://www.kbalertz.com/Feedback_823535.aspx) that states "To resolve this problem immediately, contact Microsoft Product Support Services to obtain the hotfix." Whatever happened to automatic updates? Doesn't Microsoft know that developers are busy people.....too busy to be stopped by this type of crap every time Microsoft is alerted to something they missed in the software by another developer (note:...
13
2587
by: Bryan Parkoff | last post by:
You may notice that switch (...) is much faster than function that can gain a big improved performance because it only use JMP instruction however function is required to use CALL, PUSH, and POP instruction that can be slower. I created three functions in an array. Array is called pArray_Func(). pArray_Func() contains three functions. "xx" can be used to point each function. Let say, I have over 1,000 functions. I would put "inline"...
25
10437
by: dixie | last post by:
I have some code that adds new records into a table for each ID in a list box when a button on a form is clicked. This works fine. My problem now is that I wish to be able to edit all the records for people whose ID is in the list box. I made minor changes to the code (mainly replacing rs.AddNew with rs.Edit)and it appears to be updating only the first record and then overwriting that record with the next, etc until it runs out of ID's...
19
3613
by: Raposa Velha | last post by:
Hello to all! Does any of you want to comment the approach I implement for instantiating a form? A description and an example follow. Cheers, RV jmclopesAThotmail.com replace the AT with the thing you know ;-) After discovering that access 2000 support form properties (I'm a
7
1763
by: Alan Silver | last post by:
Hello, I would like to create a new web site with VWD, but would like to run it under IIS, not the development server. One reason for this is that I want the web site to be at the domain root, not under a virtual directory. I have tried this, but don't seem to be able to get it to work. I created a new (empty) web site in IIS, and then started a new project in VWD and specified the type as HTTP. I browsed to http://test/ and
4
6727
by: Pedro Leite | last post by:
Good Afternoon. the code below is properly retreiving binary data from a database and saving it. but instead of saving at client machine is saving at the server machine. what is wrong with my code ?? thank you Pedro Leite From Portugal ------------------------------------
12
1823
by: Paul H | last post by:
A little off topic this one because the database may not be written in Access. I am just looking for some advice.. I have an idea to help prevent a particular type of crime, a database will be involved in storing and analysing information. The idea is quite a simple one and once disclosed would be easy, with reasonable technical know-how, to set-up. Police forces all over the country could use my system, but I want to approach the...
32
2720
by: andresj | last post by:
I was doing some programming in Python, and the idea came to my mind: using fractions instead of floats when doing 2/5. The problem arises when you try to represent some number, like 0.4 in a float. It will tell you that it's equal to 0.40000000000000002. "This is easy to fix", you may say. "You just use the decimal.Decimal class!". Well, firsly, there would be an excess of typing I would need to do to calculate 0.4+0.6: from decimal...
0
9825
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9671
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10852
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10553
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9382
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7793
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6980
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5651
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4459
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.