There was some code like this:
// Convenience to make things more legible in the following code
const float & x = some.buried.variable.elsewhere;
// Go on to use x in calculations...
I have been told that the "const float &" is "bad" and should just be a plain float or const float.
I, however, could not think of a compelling reason other than "you don't have to type '&'".
In fact, it seems to me that in some cases the original could be better, since compiler might not allocate extra stack space to the variable.
In other words, originally I could validly say:
assert(&x == &some.buried.variable.elsewhere)
Whereas in the second case I cannot.
Also, the original seems to communicate intent better, in my view, since the whole point of a reference is to make an alias to another value.
Can anyone give me examples of where the "const float &" version is worse than a plain "float" or "const float" in some tangible way?
I can't think of a reason why const float & would be better than const float.
References make sense if you're either worried about copies being made (which is irrelevant with a primitive type like float) or you want to be able to update a value across all instances that share the reference (which is irrelevant with const members).
On top of that, references in members are a huge pain in the neck* when it comes to initialization, and so they'd have to offer a significant advantage of the alternatives in order to be useful, and it's clearly not the case with const float.
* The FQA on references is always amusing and thought provoking
You should only use references in the following cases: (If I didn't forgot one)
The type being referred is not small and causes performance problems.
You want your local alias to update when the value being referred to is updated.
Or: You don't want to make a copy.
You want the ability to update the other value. (In case it is not constant)
So in this case the float is small enough, you probably don't want it to update when the value being referenced to updates (causing problems in your calculations) and since you are using constants you don't want it to update.
So, you would want:
const float x = some.buried.variable.elsewhere;
The address of a float may be bigger than the float itself (e.g., on 64 bits PCs).
Also it's faster to computing something with a float directly than with the address of a float (you don't have to dereference it), but maybe compilers can optimize that.
There is no reason why that reference would be wrong or bad. If what you want is a local short-cut name ("alias"), references are the way to go. If you copy the float into a new variable, then you will get a new object and as you pointed out, of course you will also get a new address: Not at all what you would have wanted. So take a reference for that:
float &x = some.buried.variable.elsewhere;
Which will behave as the original variable in expressions.
However, as with everything, hard-coded rules won't do it. It depends on the specific situation. If you don't care about the object, but rather about the object's value, then create a copy. It's better to use the float directly than have that possible indirection through a reference when all you are interested in is to get easy access to the value of something.
What is bad is to use a reference when storing the result of a computation - because what is clearly of interest is the value only. You couldn't have any interest in a temporary float identity anyway, because it doesn't exist in the first place: A temporary float is not an object. It isn't even required to have any address (which can happen if the compiler keeps the float in a register):
float const &x = 3.0; // non-sense. don't use reference here
Same with the result of a function call of course
float const &x = get_some_float(); // non-sense too.
You do not need to worry so much about stack use, especially for a single float.
If you declare a variable on the stack, nothing says that the compiler has to actually create space for it unless you take its address. Even then, if the compiler can show that the variable's address isn't used, or if the compiler can see all the uses of that address (if the function calls that get passed the address are all visible) then it still doesn't have to actually create space for the variable.
One case I can see for using the reference instead of a copy is if the value is changed through the other name, perhaps in a function call, then the reference value will change also. With a copy it wouldn't.
You mentioned that you thought the compiler might avoid allocating stack space for the reference. This may be true if you have optimization enabled, but the compiler could also optimize "const float x" by keeping the value in a FP register instead of on the stack. This is what GCC does on x86, for example.
Short answer: this code is correct, keep it this way!
Long answer:
The problem with storing the return value of a function in a reference is that you are not allocating the space to actually store the return value, so you often end up with a reference pointing to a temporary value, either the temporary return value of the function (automatically created by the compiler) or a local variable allocated during the function (and freed at its end).
This is true that you must not return a reference on a local variable because this variable will be freed when the function ends.
But the C++ standard states that the compiler must not free the temporary return value of a function if it is "const referenced". So if your function is returning a float by value, you can store this value in float reference, the compiler ensures that the actual temporary value returned by the function will not be freed until you are done with your reference.
Note that this behaviour is only valid for "const" references only.
Take a look at this Herb Sutter's article for more explanation.
Rewritten for clarity:
References are pointers in disguise with some added syntactic sugar. Pointers have any number of performance and efficiency problems. Aliasing is one notable example. The compiler can't guarantee that the memory underneath the pointer or reference is the same as the last time it read it, because any old pointer can go through and modify it. The compiler is forced to re-read the value from memory on every use rather than caching it in memory.
On most processors registers are fast, memory accesses are not. So we never want to access memory if we can avoid it. Primitive types (int, float, etc) often go into registers. The compiler has complete control over what data resides in each register and can guarantee that nothing will overwrite the value, so variables of primitive types can potentially stay in registers for a long time until the compiler needs to write any changes back out to memory.
So when dealing with primitive types, it's often less efficient to use a reference. It disallows the compiler from caching the value in a register, inserts hidden dereferences, and can open you up to performance issues arising from aliasing.
Perhaps the efficiency isn't important to you in this case, but you said you couldn't think of a good reason not to use the reference other than saving typing. I submit there is a very good reason.
Best practice with this in mind, in my opinion, would be to use references primarily for aggregate types. The compiler can't pass these around in a single register so the relative cost of using the reference is going to be heavily mitigated. If the type in question is a primitive type, I would always prefer to work with a copy of the value rather than a reference.
Whenever you are dealing with a reference you are taking a risk, which is probably why you were told to avoid this.
It is not clear what you mean by "buried variable". If you mean a member of an object (or even accessible through a sequence), there is a greater risk in that since the object could be deleted, leaving you with an invalid reference. Since you cannot aim a reference later at something else, there's no way for you to indicate that it is invalid, so a pointer might be better.
There is no problem with the const.
Can you explain what it is that you are trying to do or give more context?
Something to keep in mind: a reference-to-const doesn't necessarily mean the thing you're referencing won't change at some point. It just means you will not change the referred-to data through that reference.
So someone could theoretically change the value of some.buried.variable.elsewhere and then reading x would reflect that updated value. (Subject to the usual aliasing rules, etc, etc. Essentially, it would be updated the next time the value of x was read.)
(Feel free to comment if I'm getting anything wrong, here, I'll update or delete the answer.)
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it better to pass by value or by reference for basic datatypes?
Reasons to not pass simple types by reference?
I did some testing where I had two scenarios, each with two identical functions- one passing the parameter by reference and the other by value. The scenario with strings showed a massive performance increase (because a copy of string is made, calling a constructor) whereas the test with long didn't show any performance increase when passing the value by reference. In fact, sometimes the performance was worse.
Is this expected with primitive types? Is there no point passing them by reference?
I was expecting a copy of a primitive type is made when not using by reference and therefore expected a small performance-boost.
You get the best performance from passing primitive types by value. This is because:
primitives are blitable, so the cost of the copy depends on the size
primitives are small, only double and long long are bigger than a reference in most environments
pass-by-value avoids aliasing, allowing the optimizer to really do its thing
This last point is often overlooked but can make a considerable difference.
Yes, that's the expected behavior. When you're passing parameters by reference, you're actually passing an address of the variable (like with pointer). Usually address is a 4 or 8-byte integer, so unless your primitive type is larger than that, you won't gain any performance improvement (and even if it's larger, you probably won't)
Modern compilers are pretty clever, so if the function isn't "hidden" (that is, part of something the compiler can't see at the time of producing the code), it may well make no difference at all. HOwever, if it the compiler follows your instructions, passing simple types as reference does potentially make a big difference. Particularly if the value is updated many times in the code.
I saw some code where I worked, which did something like this:
void SomeClass::FindLength(int &len)
{
listEntry* list = theList; // theList is a member variable.
len = 0;
while (list)
{
len++;
list = list->next;
}
}
By alterning the code to do:
void SomeClass::FindLength(int &len)
{
listEntry* list = theList; // theList is a member variable.
int tempLen = 0;
while (list)
{
tempLen++;
list = list->next;
}
len = tempLen;
}
the whole code ran some 30% faster, and called from a lot of places (and I think there was some if-condition in the middle, so we couldn't just keep track of the length). And since it was part of an API function, it wasn't possible to change the function signature.
The reason it was slower using the reference is that the compiler would write to the reference value EVERY time it was updated, which was a load from memory to register, increment register and a store register to memory. With the tempLen solution, the compiler could use a register, which is much faster.
In c++ reference is just convinient way to use pointers. When you use pointer you adding additional indirection. Copying primitive types as cheap as copying pointer.
That is why primitive types passed by reference a bit slower
Because you used c tag, I guess you are speaking about pointers (not explicit references from C++).
With pointers, you have two memory access: the pointer and the pointed value. So there is no particular gain of performances. Moreover, the compiler can do more optimisations with values: there is no aliasing problems, for example.
Is this expected with primitive types?
I'd say absolutely. They don't have constructors, so that doesn't need to be called.
Is there no point passing them by reference?
There is: when you want to have output parameters, then, in C++, passing by reference is considered better pracitce than passing a pointer.
I was expecting a copy of a primitive type is made when not using by reference and therefore expected a small performance-boost.
Well, since passing by reference is usually implemented using pointers, then the compiler has to emit code that pushes something onto the stack, either the value, or a pointer to the value - and it really does not matter which one is done.
When you pass a value by reference the function must dereference it to obtain the value, and each time you modify the value a dereference must occur too since you are writing it in a memory location. I guess compilers are able to understand when something won't be stored back in its reference location so that the value is modified just on registers and stored back just when needed but I'm not sure how powerful this is.
So there is an indirect step that is not present while passing parameters by value, which can cause worse performance but it's really foggy since compiler optimizations come into place. Think about the fact that you are passing a pointer, every time you need the value you must fetch the pointer from the stack and then fetch the value pointed (so there are two accesses), while with a normal parameter you have just one (fetching the value).
In any case, a reference is used for purposes that are surely different from performance, like modifying the passed parameter locally.
With C++ how do i decide if i should pass an argument by value or by reference/pointer? (tell me the answer for both 32 and 64bits) Lets take A. Is 2 32bit values more less or equal work as a pointer to a 32bit value?
B to me seems like i always should pass by value. C i think i should pass by value but someone told me (however i haven't seen proof) that processors don't handle values not their bitsize and so it is more work. So if i were passing them around would it be more work to pass by value thus byref is faster? Finally i threw in an enum. I think enums should always be by value
Note: When i say by ref i mean a const reference or pointer (can't forget the const...)
struct A { int a, b; }
struct B { int a; }
struct C { char a, b; }
enum D { a,b,c }
void fn(T a);
Now tell me the answer if i were pushing the parameters many times and the code doesn't use a tail call? (lets say the values isnt used until 4 or so calls deep)
Forget the stack size. You should pass by reference if you want to change it, otherwise you should pass by value.
Preventing the sort of bugs introduced by allowing functions to change your data unexpectedly is far more important than a few bytes of wasted stack space.
If stack space becomes a problem, stop using so many levels (such as replacing a recursive solution with an iterative one) or expand your stack. Four levels of recursion isn't usually that onerous, unless your structures are massive or you're operating in the embedded world.
If performance becomes a problem, find a faster algorithm :-) If that's not possible, then you can look at passing by reference, but you need to understand that it's breaking the contract between caller and callee. If you can live with that, that's okay. I generally can't :-)
The intent of the value/reference dichotomy is to control what happens to the thing you pass as a parameter at the language level, not to fiddle with the way an implementation of the language works.
I pass all parameters by reference for consistency, including builtins (of course, const is used where possible).
I did test this in performance critical domains -- worst case loss compared to builtins was marginal. Reference can be quite a bit faster, for non-builtins, and when the calls are deep (as a generalization). This was important for me as I was doing quite a bit of deep TMP, where function bodies were tiny.
You might consider breaking that convention if you're counting instructions, the hardware is register-starved (e.g. embedded), or if the function is not a good candidate for inlining.
Unfortunately, the question you ask is more complex than it appears -- the answer may vary greatly by your platform, ABI, calling conventions, register counts, etc.
A lot depends on your requirement but best practice is to pass by reference as it reduces the memory foot print.
If you pass large objects by value, a copy of it is made in memory andthe copy constructor is called for making a copy of this.
So it will take more machine cycles and also, if you pass by value, changes are not reflected in the original object.
So try passing them by reference.
Hope this has been helpful to you.
Regards, Ken
First, reference and pointers aren't the same.
Pass by pointer
Pass parameters by pointers if any/some of these apply:
The passed element could be null.
The resource is allocated inside the called function and the caller is responsible should be responsible for freeing such a resource. Remember in this case to provide a free() function for that resource.
The value is of a variable type, like for example void*. When it's type is determined at runtime or depending on the usage pattern (or hiding implementation - i.e Win32 HANDLE), such as a thread procedure argument. (Here favor c++ templates and std::function, and use pointers for this purpose only if your environment does not permit otherwise.
Pass by reference
Pass parameters by reference if any/some of these apply:
Most of the time. (prefer passing by const reference)
If you want the modifications to the passed arguments to be visible to the caller. (unless const reference is used).
If the passed argument is never null.
If you know what is the passed argument type and you have control over function's signature.
Pass by copy
Pass a copy if any/some of these apply:
Generally try to avoid this.
If you want to operate on a copy of the passed argument. i.e you know that the called function would create a copy anyway.
With primitive types smaller than the system's pointer size - as it makes no performance/memory difference compared to a const ref.
This is tricky - when you know that the type implements a move constructor (such as std::string in C++11). It then looks as if you're passing by copy.
Any of these three lists can go more longer, but these are - I would say - the basic rules of thumb.
Your complete question is a bit unclear to me, but I can answer when you would use passing by value or by reference.
When passing by value, you have a complete copy of the parameter into the call stack. It's like you're making a local variable in the function call initialized with whatever you passed into it.
When passing by reference, you... well, pass by reference. The main difference is that you can modify the external object.
There is the benefit of reducing memory load for large objects passing by reference. For basic data types (32-bit or 64-bit integers, for example), the performance is negligible.
Generally, if you're going to work in C/C++ you should learn to use pointers. Passing objects as parameters will almost always be passed via a pointer (vs reference). The few instances you absolutely must use references is in the copy constructor. You'll want to use it in the operators as well, but it's not required.
Copying objects by value is usually a bad idea - more CPU to do the constructor function; more memory for the actual object. Use const to prevent the function modifying the object. The function signature should tell the caller what might happen to the referenced object.
Things like int, char, pointers are usually passed by value.
As to the structures you outlined, passing by value will not really matter. You need to do profiling to find out, but on the grand scheme of a program you be better off looking elsewhere for increasing performance in terms of CPU and/or memory.
I would consider whether you want value or reference semantics before you go worrying about optimizations. Generally you would pass by reference if you want the method you are calling to be able to modify the parameter. You can pass a pointer in this case, like you would in C, but idiomatic C++ tends to use references.
There is no rule that says that small types or enums should always be passed by value. There is plenty of code that passes int& parameters, because they rely on the semantics of passing by reference. Also, you should keep in mind that for any relatively small data type, you won't notice a difference in speed between passing by reference and by value.
That said, if you have a very large structure, you probably don't want to make lots of copies of it. This is where const references are handy. Do keep in mind though that const in C++ is not strictly enforced (even if it's considered bad practice, you can always const_cast it away). There is no reason to pass a const int& over an int, although there is a reason to pass a const ClassWithManyMembers& over a ClassWithManyMembers.
All of the structs that you listed I would say are fine to pass by value if you are intending them to be treated as values. Consider that if you call a function that takes one parameter of type struct Rectangle{int x, y, w, h}, this is the same as passing those 4 parameters independently, which is really not a big deal. Generally you should be more worried about the work that the copy constructor has to do - for example, passing a vector by value is probably not such a good idea, because it will have to dynamically allocate memory and iterate through a list whose size you don't know, and invoke many more copy constructors.
While you should keep all this in mind, a good general rule is: if you want refence semantics, pass by refence. Otherwise, pass intrinsics by value, and other things by const reference.
Also, C++11 introduced r-value references which complicate things even further. But that's a different topic.
These are the rules that I use:
for native types:
by value when they are input arguments
by non-const reference when they are mandatory output arguments
for structs or classes:
by const reference when they are input arguments
by non-const reference when they are output arguments
for arrays:
by const pointer when they are input arguments (const applies to the data, not the pointer here, i.e. const TYPE *)
by pointer when they are output arguments (const applies to the data, not the pointer)
I've found that there are very few times that require making an exception to the above rules. The one exception that comes to mind is for a struct or class argument that is optional, in which case a reference would not work. In that case I use a const pointer (input) or a non-const pointer (output), so that you can also pass 0.
If you want a copy, then pass by value. If you want to change it and you want those changes to be seen outside the function, then pass by reference. If you want speed and don't want to change it, pass by const reference.
I'm moving from Java to C++ and am a bit confused of the language's flexibility. One point is that there are three ways to store objects: A pointer, a reference and a scalar (storing the object itself if I understand it correctly).
I tend to use references where possible, because that is as close to Java as possible. In some cases, e.g. getters for derived attributes, this is not possible:
MyType &MyClass::getSomeAttribute() {
MyType t;
return t;
}
This does not compile, because t exists only within the scope of getSomeAttribute() and if I return a reference to it, it would point nowhere before the client can use it.
Therefore I'm left with two options:
Return a pointer
Return a scalar
Returning a pointer would look like this:
MyType *MyClass::getSomeAttribute() {
MyType *t = new MyType;
return t;
}
This'd work, but the client would have to check this pointer for NULL in order to be really sure, something that's not necessary with references. Another problem is that the caller would have to make sure that t is deallocated, I'd rather not deal with that if I can avoid it.
The alternative would be to return the object itself (scalar):
MyType MyClass::getSomeAttribute() {
MyType t;
return t;
}
That's pretty straightforward and just what I want in this case: It feels like a reference and it can't be null. If the object is out of scope in the client's code, it is deleted. Pretty handy. However, I rarely see anyone doing that, is there a reason for that? Is there some kind of performance problem if I return a scalar instead of a pointer or reference?
What is the most common/elegant approach to handle this problem?
Return by value. The compiler can optimize away the copy, so the end result is what you want. An object is created, and returned to the caller.
I think the reason why you rarely see people do this is because you're looking at the wrong C++ code. ;)
Most people coming from Java feel uncomfortable doing something like this, so they call new all over the place. And then they get memory leaks all over the place, have to check for NULL and all the other problems that can cause. :)
It might also be worth pointing out that C++ references have very little in common with Java references.
A reference in Java is much more similar to a pointer (it can be reseated, or set to NULL).
In fact the only real differences are that a pointer can point to a garbage value as well (if it is uninitialized, or it points to an object that has gone out of scope), and that you can do pointer arithmetics on a pointer into an array.
A C++ references is an alias for an object. A Java reference doesn't behave like that.
Quite simply, avoid using pointers and dynamic allocation by new wherever possible. Use values, references and automatically allocated objects instead. Of course you can't always avoid dynamic allocation, but it should be a last resort, not a first.
Returning by value can introduce performance penalties because this means the object needs to be copied. If it is a large object, like a list, that operation might be very expensive.
But modern compilers are very good about making this not happen. The C++ standards explicitly states that the compiler is allowed to elide copies in certain circumstances. The particular instance that would be relevant in the example code you gave is called the 'return value optimization'.
Personally, I return by (usually const) reference when I'm returning a member variable, and return some sort of smart pointer object of some kind (frequently ::std::auto_ptr) when I need to dynamically allocate something. Otherwise I return by value.
I also very frequently have const reference parameters, and this is very common in C++. This is a way of passing a parameter and saying "the function is not allowed to touch this". Basically a read-only parameter. It should only be used for objects that are more complex than a single integer or pointer though.
I think one big change from Java is that const is important and used very frequently. Learn to understand it and make it your friend.
I also think Neil's answer is correct in stating that avoiding dynamic allocation whenever possible is a good idea. You should not contort your design too much to make that happen, but you should definitely prefer design choices in which it doesn't have to happen.
Returning by value is a common thing practised in C++. However, when you are passing an object, you pass by reference.
Example
main()
{
equity trader;
isTraderAllowed(trader);
....
}
bool isTraderAllowed(const equity& trdobj)
{
... // Perform your function routine here.
}
The above is a simple example of passing an object by reference. In reality, you would have a method called isTraderAllowed for the class equity, but I was showing you a real use of passing by reference.
A point regarding passing by value or reference:
Considering optimizations, assuming a function is inline, if its parameter is declared as "const DataType objectName" that DataType could be anything even primitives, no object copy will be involved; and if its parameter is declared as "const DataType & objectName" or "DataType & objectName" that again DataType could be anything even primitives, no address taking or pointer will be involved. In both previous cases input arguments are used directly in assembly code.
A point regarding references:
A reference is not always a pointer, as instance when you have following code in the body of a function, the reference is not a pointer:
int adad=5;
int & reference=adad;
A point regarding returning by value:
as some people have mentioned, using good compilers with capability of optimizations, returning by value of any type will not cause an extra copy.
A point regarding return by reference:
In case of inline functions and optimizations, returning by reference will not involve address taking or pointer.
I'm moving from Java to C++ and am a bit confused of the language's flexibility. One point is that there are three ways to store objects: A pointer, a reference and a scalar (storing the object itself if I understand it correctly).
I tend to use references where possible, because that is as close to Java as possible. In some cases, e.g. getters for derived attributes, this is not possible:
MyType &MyClass::getSomeAttribute() {
MyType t;
return t;
}
This does not compile, because t exists only within the scope of getSomeAttribute() and if I return a reference to it, it would point nowhere before the client can use it.
Therefore I'm left with two options:
Return a pointer
Return a scalar
Returning a pointer would look like this:
MyType *MyClass::getSomeAttribute() {
MyType *t = new MyType;
return t;
}
This'd work, but the client would have to check this pointer for NULL in order to be really sure, something that's not necessary with references. Another problem is that the caller would have to make sure that t is deallocated, I'd rather not deal with that if I can avoid it.
The alternative would be to return the object itself (scalar):
MyType MyClass::getSomeAttribute() {
MyType t;
return t;
}
That's pretty straightforward and just what I want in this case: It feels like a reference and it can't be null. If the object is out of scope in the client's code, it is deleted. Pretty handy. However, I rarely see anyone doing that, is there a reason for that? Is there some kind of performance problem if I return a scalar instead of a pointer or reference?
What is the most common/elegant approach to handle this problem?
Return by value. The compiler can optimize away the copy, so the end result is what you want. An object is created, and returned to the caller.
I think the reason why you rarely see people do this is because you're looking at the wrong C++ code. ;)
Most people coming from Java feel uncomfortable doing something like this, so they call new all over the place. And then they get memory leaks all over the place, have to check for NULL and all the other problems that can cause. :)
It might also be worth pointing out that C++ references have very little in common with Java references.
A reference in Java is much more similar to a pointer (it can be reseated, or set to NULL).
In fact the only real differences are that a pointer can point to a garbage value as well (if it is uninitialized, or it points to an object that has gone out of scope), and that you can do pointer arithmetics on a pointer into an array.
A C++ references is an alias for an object. A Java reference doesn't behave like that.
Quite simply, avoid using pointers and dynamic allocation by new wherever possible. Use values, references and automatically allocated objects instead. Of course you can't always avoid dynamic allocation, but it should be a last resort, not a first.
Returning by value can introduce performance penalties because this means the object needs to be copied. If it is a large object, like a list, that operation might be very expensive.
But modern compilers are very good about making this not happen. The C++ standards explicitly states that the compiler is allowed to elide copies in certain circumstances. The particular instance that would be relevant in the example code you gave is called the 'return value optimization'.
Personally, I return by (usually const) reference when I'm returning a member variable, and return some sort of smart pointer object of some kind (frequently ::std::auto_ptr) when I need to dynamically allocate something. Otherwise I return by value.
I also very frequently have const reference parameters, and this is very common in C++. This is a way of passing a parameter and saying "the function is not allowed to touch this". Basically a read-only parameter. It should only be used for objects that are more complex than a single integer or pointer though.
I think one big change from Java is that const is important and used very frequently. Learn to understand it and make it your friend.
I also think Neil's answer is correct in stating that avoiding dynamic allocation whenever possible is a good idea. You should not contort your design too much to make that happen, but you should definitely prefer design choices in which it doesn't have to happen.
Returning by value is a common thing practised in C++. However, when you are passing an object, you pass by reference.
Example
main()
{
equity trader;
isTraderAllowed(trader);
....
}
bool isTraderAllowed(const equity& trdobj)
{
... // Perform your function routine here.
}
The above is a simple example of passing an object by reference. In reality, you would have a method called isTraderAllowed for the class equity, but I was showing you a real use of passing by reference.
A point regarding passing by value or reference:
Considering optimizations, assuming a function is inline, if its parameter is declared as "const DataType objectName" that DataType could be anything even primitives, no object copy will be involved; and if its parameter is declared as "const DataType & objectName" or "DataType & objectName" that again DataType could be anything even primitives, no address taking or pointer will be involved. In both previous cases input arguments are used directly in assembly code.
A point regarding references:
A reference is not always a pointer, as instance when you have following code in the body of a function, the reference is not a pointer:
int adad=5;
int & reference=adad;
A point regarding returning by value:
as some people have mentioned, using good compilers with capability of optimizations, returning by value of any type will not cause an extra copy.
A point regarding return by reference:
In case of inline functions and optimizations, returning by reference will not involve address taking or pointer.
I'm wondering with functions like the following, whether to use a temporary variable (p):
void parse_foo(const char*& p_in_out,
foo& out) {
const char* p = p_in_out;
/* Parse, p gets incremented etc. */
p_in_out = p;
}
or can I just use the original argument and expect it to be optimized similarly to the above anyway? It seems like there should be such an optimization, but I've seen the above done in a few places such as Mozilla's code, with vague comments about "avoiding aliasing".
All good answers, but if you're worried about performance optimization, the actual parsing is going to take nearly all of the time, so pointer aliasing will probably be "in the noise".
The variant with a temporary variable could be faster since it doesn't imply that every change to the pointer is reflected back to the argument and the compiler has better chances on generating faster code. However the right way to test this is to compile and look at the disassembly.
Meanwhile this has noting to do with avoiding aliasing. In fact, the variant with a temporary variant does employ aliasing - now you have two pointers into the same array and that's exactly what aliasing is.
I would use a temporary if there is a possibility that the function is transactional.
i.e. the function succeeds or fails completely (no middle ground).
In this case I would use a temp to maintain state while the function executes and only assign back to the in_out parameter when the function completes successfully.
If the function exits prematurely (ie via exception) then we have two situations:
With a temporary (the external pointer is unchanged)
Using the parameter directly the external state is modified to reflect position.
I don't see any optimization advantages to either method.
Yes, you should assign it to a local that you mark restrict (__restrict in MSVC).
The reason for this is that if the compiler cannot be absolutely sure that nothing else in the scope points at p_in_out, it cannot store the contents under the pointer in a local register. It must read the data back every time you write to any other char * in the same scope. This is not an issue of whether it is a "smart" compiler or not; it is a consequence of correctness requirements.
By writing char* __restrict p you promise the compiler that no other pointer in the same scope points to the same address as p. Without this guarantee, the value of *p can change any time any other pointer is written to, or it may change the contents of some other pointer every time *p is written to. Thus, the compiler has to write out every assignment to *p back to memory immediately, and it has to read them back after every time another pointer is written through.
So, guaranteeing the compiler that this cannot happen — that it can load *p exactly once and assume no other pointer affects it — can be an improvement in performance. Exactly how much depends on the particular compiler and situation: on processors subject to a load-hit-store penalty, it's massive; on most x86 CPUs, it's modest.
The reason to prefer a pointer to a reference here is simply that a pointer can be marked restrict and a reference cannot. That's just the way C++ is.
You can try it both ways and measure the results to see which is really faster. And if you're curious, I've written in depth on restrict and the load-hit-store elsewhere.
addendum: after writing the above I realize that the people at Moz were more worried about the reference itself being aliased -- that is, that something else might point at the same address where const char *p is stored, rather than the char to which p points. But my answer is the same: under the hood, const char *&p means const char **p, and that's subject to the same aliasing issues as any other pointer.
How does the compiler know that p_in_out isn't aliased somehow? It really can't optimize away writing the data back through the reference.
struct foo {
setX(int); setY(int);
const char* current_pos;
} x;
parse_foo(x.current_pos, x);
I look at this and ask why you didn't just return the pointer Then you don't have a reference to a pointer and you don't have to worry about modify the original.
const char* parse_foo(const char* p, foo& out) {
//use p;
return p;
}
It also means you can call the function with an rvalue:
p = parse_foo(p+2, out);
One thought that comes immediately in mind: exception safety. If you throw an exception during parsing, the use of a temporary variable is what you should do to provide strong exception safety: Either the function call succeeded completely or it didn't do anything (from a user's perspective).