I have seen functions defined these two ways:

function(type *variablename)
function(type variablename&)

I commonly use the first one to pass on pointers to my structs, but is the second one the same as the first?

9 Years
Discussion Span
Last Post by VBNick

It's the same thing -- once the code has been compiled -- and used for the same purpose. It's better to use the second way, passing "by reference," because the first desensitizes you toward pointers. (Your spidey sense should tingle when you see a pointer -- it means danger lurks.)

It's very common, especially, for functions to take arguments passed by a const reference.


I'm sorrrry..I don't understand, maybe because I put the & in the wrong place above.

this here is the function in question, copied from the project.

f32 dot_xyz( const sVec4& other) const
	return x*other.x + y*other.y + z*other.z;
//I would usually do it like this:
f32 dot_xyz(sVec4 *other)
	return x*other.x + y*other.y + z*other.z;

I would use it to reference the variable used for input rather than make a copy for my function.
I dont understand why "&" is used, and why "const" would be put infront of the argument like that....and the one at the end? im confused =/ and why does danger lurk when using pointers?


The danger lurks because the pointer could be null, or the pointer could be pointing at something that no longer exists. It's easy for programmers to make mistakes like that. It's slightly harder to do this with references. Also, there ends up being less syntax involved, and the person using the function doesn't have to wonder whether the argument may be a pointer to an array.

The reason the first const is used in that code example (in const sVec4& other ) is because that means the function is promising not to modify the value of 'other'. It receives a reference to the variable and promises not to modify it (and if a developer accidentally tried to do so later, the code wouldn't compile). There are other de facto agreements too -- because the variable's passed by reference, the function won't do anything that assumes the variable exists after it has returned. I mean, it could, but that would look weird and the programmer would have to be really drunk to do such a thing.

The reason for the second const, that goes after the argument list, is to promise that the function dot_xyz won't modify the object it's called with. Suppose the function dot_xyz is a member of the class X. If you had a const X lying around somewhere, you would not be able to call the member function dot_xyz if it didn't have that const declaration.

The reason const declarations are useful is because functions that modify values of third-party objects are hard to reason about. It's easiest to reason about code when there are clearly defined inputs and outputs. When functions modify third-party objects, they're secretly communicating information to the outside world. This is known as "spooky action at a distance." Programs are much more maintainable when functions communicate information in a straightforward fashion, by returning values or by modifying arguments explicitly passed to receive information. (It's often expensive to return big values like vectors, because you have to make a copy -- so people pass in an empty vector as an argument instead.) If your objects are modifiable, you'll end up having to make "defensive copies" of your objects so that you know that the local copy can't be modified. This slows down the performance of your code. And this slowdown is the main reason why some C++ applications run slower than counterparts written in other, slower languages. (Another reason for unnecessary copying is the fact that C++ uses manual memory management. And there are unrelated ways to avoid those kinds of copies.)

A lot of times, you'll see objects that get filled with information for a brief period of time, where only one object knows about its existence. But when it gets released to the outside world, it gets "frozen" -- you can only access const versions of the object.


Okay, Thanks! I think I understand now. I should use (type &var) for a single variable, and only use (type *var) if I have to send an array. The "const" thing I supposed would only be applicable if I was making a class or software for someone else, so I guess I'll get to using that some other time. Thanks again.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.