C++/C -assembly level questions - c++

When a global variable is used inside a function(C/C++), whether it'll be taken directly from registers or from stack?
Why bound loops(for loops) are considered to have more scope for optimization than nobound loops(while loop/do while)?
Why returning a value is not as good as passing the value by reference?
If possible plz give assembly level descriptions.

1) It will be taken from an address allocated as part of the application load. ie A global variable is simply an address in the process's virtual address space. If that global has been used recently the compiler may be able to cache it in a register.
2) They don't.
3) Returning a value often requires a copy of the data. If the data is a simple type (such as int or float) then it can and will be returned via a register. If the object is too large to fit in a register then the compiler must allocate space for the object on the stack and then copy the data being returned into this allocated space. Passing the value as a reference is, usually, implemented by passing a pointer to the data. Therefore you return the value by modifying the data at that memory address directly. No copy takes place and hence its faster. Do note, though, that Return Value Optimisation (RVO) can mean that there is no win to passing the return value in as a reference. Equally,a s pointed out in the comments, C++0x's new move constructor can also provide the same bonuses as RVO.
No need to explain any of those using assembler examples, IMO.

1) Global variable is statically allocated by linker
(it can be an offset from module's base though, not
necessarily a fixed address).
Still, a function would usually read a global var from
a direct address, and a local var from offset + stack pointer
and a class field from offset + object base pointer.
The value of a global variable can be cached in a register
for subsequent reads, unless its declared "volatile".
2) Its not really a matter of for/do/while choice,
but how easy its to compute the number of iterations,
so that compiler would be able to decide whether to unroll
and/or vectorize and/or parallelize the loop.
For example, here the compiler would know the number
of iterations:
for( i=0; i<8; i++ ) { j = 1 << i; XXX }
and here it won't:
for( j=1; j<256; j<<=1 ) { XXX }
The for loops maybe just more frequently have a structure
which is easier to understand for compiler.
3) If its a value of basic type (char/short/int etc), its
slower to return it by reference (though sometimes compiler
can optimize this).
But for larger structures a reference/pointer can reduce
the amount of work for compiler, and it really may be faster
if compiler won't be able to avoid creating some temporary
copies etc.
Update:
Ok, here's a more specific example:
#include <stdio.h>
int main( void ) {
int a,b, i,j,s1,s2;
a = 123 + printf(""); // unknown in compile time
s1 = 1;
// bit reverse loop v1, gets unrolled
for( i=0; i<8; i++ ) { j = 1 << i; s1 += s1 + ((a&j)>0); }
s1 -= 256;
b = s1 + printf("");
// bit reverse loop v2, not unrolled
for( s2=1; s2<256; s2+=s2+(j>0) ) { j = b & s2; b -= j; }
s2 -= 256;
printf( "a=%02X s1=%02X s2=%02X\n", a, s1, s2 );
}
Asm listings for gcc/intelc are available here: http://nishi.dreamhosters.com/u/1.zip

First off you have not specified a target platform, arm, x86, 6502, zpu, etc.
1) When a global variable is used inside a function(C/C++), whether it'll be taken directly from registers or from stack?
You were not clear, so a global can be passed in by value, by reference or not passed in and used directly in the function.
passed by value depends on the code/compiler/target which you didnt specify. So the value or address to the global can go in a register or on the stack depending on the calling convention for that compiler/target. Items passed in by register sometimes have a placeholder on the stack in case the function needs more registers than are available. So passed by value the value the global contained is initially accessed either in a register or on the stack.
passed by reference is pretty much the same as passed by value, instead of the value the address to the global is passed in by register or on the stack depending on the compiler/target. Where this differs is that you can access the global directly from/to its memory location, but that is the nature of pass by reference.
used directly in the function then it depends on the code/compiler/target as to whether the global is accessed directly from its fixed memory location or if a register loads that memory location and the value is operated on from a register. The stack is not used in this case so the answer is either (non-stack) memory or register.
2) Why bound loops(for loops) are considered to have more scope for optimization than nobound loops(while loop/do while)?
Depends on the code, compiler, and target, I cannot think of a generic case where one is better than the other.
3) Why returning a value is not as good as passing the value by reference?
Very very subtle performance gain if anything. Depends heavily on the code, compiler, and target. There are cases where by reference is slightly faster and cases where by value is slightly faster. Comparing the two, the differences have to do with the number of times the address or data has to be copied to/from registers or the stack on its path. At best you may save a few mov or load/store instructions.

In the general case (being precise here is hard), globals are retrieved from memory but not from the stack (unless already cached in a register), loops can be optimized depending on the information that the compiler has on what the loop does (can it perform loop unrolling?) and in the third case it depends on the actual code. Since the first two have already been dealt with in other questions, I will focus on the third question.
There is a common optimization called (Named) Return Value Optimization (N)RVO that the compiler can perform to avoid unnecessary copies.
// RVO // NRVO // cannot perform RVO
type foo() { type bar() { type baz() {
value a; type a; type a,b;
// operate on a // modify a // pass a and b to other functions
return type(a); return a; if ( random() > x ) return a;
} } else return b;
}
In both foo and bar, the compiler is able to analyze the code and determine that the temporary type(a) in foo or the named local variable a in bar are the return value of the function, so it can construct those objects in place of the return value (according to the calling convention) and avoid copying it. Contrast that with baz where the compiler must create objects a and b before actually knowing which has to be returned. In this case the compiler cannot optimize anything, has to perform the operations and only at the end copy either a or b to the return value.
Whenever the compiler performs (N)RVO or if it is actually impossible to perform, changing the function signature to receive the object by reference will not provide a performance advantage and will make code at the place of call less readable for functions that create new objects.
This should be used as a general rule of thumb, but noting that as always, there are exceptions, and cases where one or the other might be slightly better performance wise. But for most cases, and unless measuring the performance proves otherwise, you should write the code as close to the design semantics as possible. If a function creates a new object, then return it by value, if a functions modifies an object, pass by reference.
Some special cases can be a function that creates vectors and is called in a tight loop, where having a single vector that is pass by reference, cleared in the function and then filled will reduce the number of memory allocations (clear() in a vector does not deallocate memory, so it does not need to reallocate it in the next iteration).
On the other end, when function calls are chained, and with the proper combination of return bay value and pass by value, you might avoid extra copies by not passing references in --a non-const reference requires a non-temporary object.

Related

Function Return Mechanism:Temporary object, R-Value, L-Value

Analyzing the question on its low level, when a function returns a value, it is returned either in a cpu register, or in a space allocated on the stack previously by the caller.
At this point the calling function can take the value and copy it into its local variable.
int sum(int a,int b){return a + b;}
int main(){int risultato = sum(10,20);return 0;}
in this case the sum function returns the value in the EAX register. Then the main function copies the value from the eax register into a memory location on the stack.
This is what really happens.
Moving now to the abstraction of C ++, if I tried to do an operation like this:
sum (10.20) = 4;
it gives me an error.
This is because basically the function is not returning the memory location in which the value is contained, but the value itself.
Being therefore an r-value, this will not be assignable, since it is not possible to assign a value to another value.
The issue becomes completely different when the dereferencing operator * is used.
In this case, it will not be returned a value, but the memory location itself (l-value), which will therefore be assignable.
Is what I wrote correct?
Let's take now this second exemple.
class class1 {public: int i; int b; class1(int i,int b) { this->i = i;this->b = b; }};
class1 fun() { class1 c(10,5); return c; }
int main() {fun().i = 4; return 0;}
in this case the function returns an object.
If I try to execute an instruction like this:
fun (). i = 4; I always get an error.
I know that when the function is called a temporary object is created on the stack.
Returning the function an object , but not as a variable (l-value), but as a set of values, it will not be possible to assign one of these with the value 4.
The same problem also seems to exist with this statement here:
class1(10,20).i = 4;
In this case I am creating a temporary object, I don't understand why it doesn't give me the possibility to assign the object's variable i, why in this case is it always interpreted as an r-value and not as an l-value?
I know that what I am doing has no use in practice, but it remains a purely theoretical question, which I need to understand the syntax of language correctly.
Could you comment everything I have said so far, expressing your point of view, and trying to answer the final question?
Moving now to the abstraction of C ++, if I tried to do an operation like this: sum (10.20) = 4; it gives me an error. This is because basically the function is not returning the memory location in which the value is contained, but the value itself. Being therefore an r-value, this will not be assignable, since it is not possible to assign a value to another value. The issue becomes completely different when the dereferencing operator * is used. In this case, it will not be returned a value, but the memory location itself (l-value), which will therefore be assignable.
Is what I wrote correct?
Kind of. You say
This is because basically the function is not returning the memory location in which the value is contained
But that is not what happens. An object is returned, that object has a value. What makes it an rvalue is that the function "returns by value" (another name for makes a temporary object).
Being therefore an r-value, this will not be assignable, since it is not possible to assign a value to another value
This is only true for built in types. The assignment operator of built in types requires that the object being assigned to be an lvalue. If you have a user defined type (class, struct) then you can assign to an rvalue.
In this case I am creating a temporary object, I don't understand why it doesn't give me the possibility to assign the object's variable i, why in this case is it always interpreted as an r-value and not as an l-value?
The reason is that with operator . if the object you call it on is an rvalue, then the member you access is treated as an rvalue. Since i is a built in type, and an rvalue, you can't assign to it.
I know that what I am doing has no use in practice
This is the answer to your question:
Why in this case is it always interpreted as an r-value and not as an l-value?
It's harder to implement the compiler if it needs to make this an L-Value, and since it has no use, it's not worth the trouble.
There are some things that are just for the convenience of compiler writers.
#NathanOliver answered the C++ abstract machine part. I'll just add a note about how that maps to asm.
Then the main function copies the value from the eax register into a memory location on the stack.
Or not, if the optimizing compiler just keeps risultato in a register like EAX. Or optimizes it away completely because in this case it's unused.
In abstract C every object has a memory address (except for register int foo variables), but in practice unless you disable optimization variables only have addresses if the compiler runs out of registers.
The return-value object is in EAX.
Notice that mainstream C++ calling conventions only ever return trivially-copyable objects in registers. A non-trivial constructor or destructor will force even a struct of one member to be returned by hidden pointer, to make sure the constructor and destructor have a consistent this. (Calling convention rules can't depend on the content of the constructor and destructor functions, just whether either is defined at all.)

Usage of const and references in parameters in c++ [duplicate]

This question already has answers here:
Pass int by const reference or by value , any difference? [duplicate]
(4 answers)
Closed 4 years ago.
There are multiple ways of making a method. I'm not quite sure when to use const and reference in method parameters.
Imagine a method called 'getSum' that returns the sum of two integers. The parameters in such a method can have multiple forms.
int getSum1(int, int);
int getSum2(int&, int&);
int getSum3(const int, const int);
int getSum4(const int&, const int&);
Correct me if I'm wrong, but here's how I see these methods:
getSum1 - Copies integers and calculates
getSum2 - Doesn't copy integers, but uses the values directly from memory and calculates
getSum3 - Promises that the values won't change
getSum4 - Promises that the values won't change & doesn't copy the integers, but uses the values directly from memory
So here are some questions:
So is getSum2 faster than getSum1 since it doesn't copy the integers, but uses them directly?
Since the values aren't changed, I don't think 'const' makes any difference in this situation, but should it still be there for const correctness?
Would it be the same with doubles?
Should a reference only be used with very large parameters? e.g. if I were to give it a whole class, then it would make no sense to copy the whole thing
For integers, this is irrelevant in practice. Processors work with registers (and an int fits in a register in all but the most exotic hardware), copying a register is basically the cheapest operation (after a noop) and it may not even be necessary if the compiler allocates registers in a smart way.
Use this if you want to change the passed ints. Non-const reference parameters generally indicate that you intend to modify the argument (for example, store multiple return values).
This does exactly the same as 1. for basically the same reason. You cannot change the passed ints but nobody would be any the wiser if you did (i.e. used 1. instead).
Again, this will effectively do the same thing as 1. for ints (or doubles, if your CPU handles them natively) because the compiler understands that passing a const pointer to an int (or double) is the same as providing a copy, but the latter avoids unnecessary trips to memory. Unless you take a pointer to the arguments (in which case the compiler would have to guarantee it points to the int on the call site) this is thus pointless.
Note that the above is not in terms of the C++ abstract machine but in terms of what happens with modern hardware/compilers. If you are working on hardware without dedicated floating point capabilities or where ints don't fit in registers, you have to be more careful. I don't have an overview over current embedded hardware trends, but unless you literally write code for toasters, you should be good.
If you are not dealing with ints but with (large) classes, then the semantic differences are much stronger:
The function receives a copy. Note that if you pass in a temporary, that copy may be move-constructed (or even better, elided).
Same as in the "int section", use this over 4. only if you want to change the passed value.
You receive a copy that cannot be changed. This is generally not very useful outside of specific circumstances (or for marginal code clarity increases).
This should be the default to pass a large class (well, pretty much anything bigger than a pointer) if you intend to only read from (or call const methods on) it.
You are correct. the values of a and b would not be copied. But the addresses to a and b would be copied, and in this case you would not gain any speed since int and pointer to int are of the same (or about the same) size. You would gain speed if the size of the arguments to the function is large, like a struct or class as you mention in Q4.
2)
Const means that you can not change the value of the parameter. If it is not declared as a const you can change it inside the function, but the original value or variable you used when calling the function will not be changed.
int getSum1(int a, int b)
{
a = a + 5;
return a + b;
}
int a, b, foo;
a = 10;
b = 5;
foo = getSum1(a, b);
In this case foo has the value 20
a equals 10
b equals 5
Since the modification of a is only local to the function getSum1()

How to return object more efficient without copying [duplicate]

When a function (callee) returns a quantity to the caller function, is it returned by
value or by reference?
The thing is I have written a function which builds a very large vector of when called. I want to return this big vector to the calling function , ( in this case main() ) by constant reference so I can do some further processing on it.
I was in doubt because I was told that when a C++ function returns and terminates, all the variables/memory associated with that function, get wiped clean.
struct node{
string key;
int pnum;
node* ptr;
}
vector< vector<node> > myfun1(/*Some arguments*/)
{
/*Build the vector of vectors. Call it V*/
return v;
}
int main(void)
{
a=myfun1(/* Some arguments */)
}
C++ functions can return by value, by reference (but don't return a local variable by reference), or by pointer (again, don't return a local by pointer).
When returning by value, the compiler can often do optimizations that make it equally as fast as returning by reference, without the problem of dangling references. These optimizations are commonly called "Return Value Optimization (RVO)" and/or "Named Return Value Optimization (NRVO)".
Another way to for the caller to provide an empty vector (by reference), and have the function fill it in. Then it doesn't need to return anything.
You definitely should read this blog posting: Want Speed? Pass by value.
By default, everything in C/C++ is passed by value, including return type, as in the example below:
T foo() ;
In C++, where the types are usually considered value-types (i.e. they behave like int or double types), the extra copy can be costly if the object's construction/destruction is not trivial.
With C++03
If you want to return by reference, or by pointer, you need to change the return type to either:
T & foo() ; // return a reference
T * foo() ; // return a pointer
but in both cases, you need to make sure the object returned still exists after the return. For example, if the object returned was allocated on stack in the body of the function, the object will be destroyed, and thus, its reference/pointer will be invalid.
If you can't guarantee the object still exists after the return, your only solution is to either:
accept the cost of an extra copy, and hope for a Return Value Optimization
pass instead a variable by reference as a parameter to the function, as in the following:
void foo(T & t) ;
This way, inside the function, you set the t value as necessary, and after the function returns, you have your result.
With C++11
Now, if you have the chance to work with C++0x/C++11, that is, with a compiler that supports r-values references/move semantics, if your object has the right constructor/operator (if your object comes from the standard library, then it's ok), then the extra temporary copy will be optimized away, and you can keep the notation:
T foo() ;
Knowing that the compiler will not generate an unnecessary temporary value.
C++ can return either by reference or by value. If you want to return a reference, you must specify that as part of the return type:
std::vector<int> my_func(); // returns value
std::vector<int>& my_func(); // returns reference
std::vector<int> const& my_func(); // returns constant reference
All local (stack) variables created inside of a function are destroyed when the function returns. That means you should absolutely not return locals by reference or const reference (or pointers to them). If you return the vector by value it may be copied before the local is destroyed, which could be costly. (Certain types of optimizations called "return value optimization" can sometimes remove the copy, but that's out of the scope of this question. It's not always easy to tell whether the optimization will happen on a particular piece of code.)
If you want to "create" a large vector inside of a function and then return it without copying, the easiest way is to pass the vector in to the function as a reference parameter:
void fill_vector(std::vector<int> &vec) {
// fill "vec" and don't return anything...
}
Also note that in the recently ratified new version of the C++ standard (known as C++0x or C++11) returning a local vector by value from a function will not actually copy the vector, it will be efficiently moved into its new location. The code that does this looks identical to code from previous versions of C++ which could be forced to copy the vector. Check with your compiler to see whether it supports "move semantics" (the portion of the C++11 standard that makes this possible).
It's returned by whatever you declare the return type to be. vector<int> f(); and vector<int>& f(); return by value and reference respectively. However, it would be a grave error to return a reference to a local variable in the function as it will have been blown away when the function scope exits.
For good tips on how to efficiently return large vectors from a function, see this question (in fact this one is arguably a duplicate of that).
The function will return what you tell it to return. If you want to return a vector, then it will be copied to the variable hold by the caller. Unless you capture that result by const reference, in which case there is no need to copy it. There are optimizations that allow functions to avoid this extra copy-constructon by placing the result in the object that will hold the return value. You should read this before changing your design for performance:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
Like most things in C++, the answer is "it depends on how you defined the function".
The default for the language is return-by-value. A simple call like "double f()" is going to always return the floating-point number by value. However, you CAN return values by pointer or by reference- you just add the extra symbols '&' or '*' to the return type:
// Return by pointer (*)
T* f();
// Return by reference (a single '&')
T& f();
However, these are ridiculously unsafe in many situations. If the value the function is returning was declared within the function, the returned reference or pointer will point to random garbage instead of valid data. Even if you can guarantee that the pointed-to data is still around, this kind of return is usually more trouble than it is worth given the optimizations all modern C++ compilers will do for you. The idiomatic, safe way to return something by reference is to pass a named reference in as a parameter:
// Return by 'parameter' (a logical reference return)
void f(T& output);
Now the output has a real name, and we KNOW it will survive the call because it has to exist before the call to 'f' is even made. This is a pattern you will see often in C++, especially for things like populating a STL std::vector. Its ugly, but until the advent of C++11 it was often faster than simply returning the vector by value. Now that return by value is both simpler and faster even for many complex types, you will probably not see many functions following the reference return parameter pattern outside of older libraries.
All variables defined on the stack are cleaned upon exit.
To return a variable you should allocate it on the heap, which you do with the new keyword (or malloc).
Classes and structs are passed around as pointers, while the primitive types are passed around as values.

C++ - Reference, Pointers in Arguments

There are many questions about "when do I use reference and when pointers?". They confused me a little bit. I thought a reference wouldn't take any memory because it's just the address.
Now I made a simple Date class and showed them the community of code-review. They told me not to use the reference in the following example. But why?
Someone told me that it'll allocate the same memory a pointer would allocate. That's the opposite of what I learned.
class A{
int a;
public:
void setA(const int& b) { a = b; } /* Bad! - But why?*/
};
class B{
int b;
public:
void setB(int c) { b = c; } /* They told me to do this */
};
So when do I use references or pointers in arguments and when just a simple copy? Without the reference in my example, is the constant unnecessary?
It is not guaranteed to be bad. But it is unnecessary in this specific case.
In many (or most) contexts, references are implemented as pointers in disguise. Your example happens to be one of those cases. Assuming that the function does not get inlined, parameter b will be implemented "under the hood" as a pointer. So, what you really pass into setA in the first version is a pointer to int, i.e. something that provides indirect access to your argument value. In the second version you pass an immediate int, i.e. something that provides direct access to your argument value.
Which is better and which is worse? Well, a pointer in many cases has greater size than an int, meaning that the first variant might passes larger amount of data. This might be considered "bad", but since both data types will typically fit into the hardware word size, it will probably make no appreciable difference, especially if parameters are passed in CPU registers.
Also, in order to read b inside the function you have to dereference that disguised pointer. This is also "bad" from the performance point of view.
These are the formal reasons one would prefer to pass by value any parameters of small size (smaller or equal to pointer size). For parameters or bigger size, passing by const reference becomes a better idea (assuming you don't explicitly require a copy).
However, in most cases a function that simple will probably be inlined, which will completely eliminate the difference between the two variants, regardless of which parameter type you use.
The matter of const being unnecessary in the second variant is a different story. In the first variant that const serves two important purposes:
1) It prevents you from modifying the parameter value, and thus protects the actual argument from modification. If the reference weren't const, you would be able to modify the reference parameter and thus modify the argument.
2) It allows you to use rvalues as arguments, e.g. call some_obj.setA(5). Without that const such calls would be impossible.
In the second version neither of this is an issue. There's no need to protect the actual argument from modification, since the parameter is a local copy of that argument. Regardless of what you do to the parameter, the actual argument will remain unchanged. And you can already use rvalues as arguments to SetA regardless of whether the parameter is declared const or not.
For this reason people don't normally use top-level const qualifiers on parameters passed by value. But if you do declare it const, it will simply prevent you from modifying the local b inside the function. Some people actually like that, since it enforces the moderately popular "don't modify original parameter values" convention, for which reason you might sometimes see top-level const qualifiers being used in parameter declarations.
If you has light-weight type like a int or long you should use passing by value, because there won't be additional costs from work with references. But when you passing some heavy types, you should use references
I agree with the reviewer. And here's why:
A (const or non-const) reference to a small simple type, such as int will be more complex (in terms of number of instructions). This is because the calling code will have to pass the address of the argument into setA, and then inside setA the value has to be dereferenced from the address stored in b. In the case where b is a plain int, it just copies the value itself. So there is at least one step of a memory reference in saving. This may not make much of a difference in a long runtime of a large program, but if you keep adding one extra cycle everywhere you do this, then it does soon add up to noticeably slower.
I had a look at a piece of code that went something like this:
class X
{
vector v;
public:
...
void find(int& index, int b);
....
}
bool X::find(int &index, int b)
{
while(v[index] != b)
{
if (index == v.size()-1)
{
return false;
}
index++;
}
return true;
}
Rewriting this code to:
bool X::find(int &index, int b)
{
int i = index;
while(v[i] != b)
{
if (i == v.size()-1)
{
index = i;
return false;
}
i++;
}
index = i;
return true;
}
meant that this function went from about 30% of the total execution of some code that called find quite a bit, to about 5% of the execution time of the same test. Because the compiler put i in a register, and only updated the reference value when it finished searching.
References are implemented as pointers (that's not a requirement, but it's universally true, I believe).
So in your first one, since you're just passing an "int", passing the pointer to that int will take about the same amount of space to pass (same or more registers, or same or more stack space, depending on your architecture), so there's no savings there. Plus now you have to dereference that pointer, which is an extra operation (and will almost surely cause you to go to memory, which you might not have to do with the second one, again, depending on your architecture).
Now, if what you're passing is much larger than an int, then the first one could be better because you're only passing a pointer. [NB that there are cases where it still might make sense to pass by value even for a very large object. Those cases are usually when you plan to create your own copy anyway. In that case, it's better to let the compiler do the copy, because the overall approach may improve it's ability to optimize. Those cases are very complex, and my opinion is that if you're asking this question, you should study C++ more before you try to tackle them. Although they do make for interesting reading.]
Passing primitives as const-reference does not save you anything. A pointer and an int use the same amount of memory. If you pass a const-reference, the machine will have to allocate memory for a pointer and copy the pointer address, which has the same cost as allocating and copying an integer. If your Date class uses a single 64-bit integer (or double) to store the date, then you don't need to use const-reference. However, if your Data class becomes more complex and stores additional fields, then passing the Date object by const-reference should have a lower cost than passing it by value.

General question: What to pass as pointer in C/C++?

Hey there,
I wonder if it's worth passing primitive single values like int, float, double or char by pointer? Probably it's not worth!? But if you would simply pass everything by pointer, is this making the program slower?
Should you always just pass arrays as pointer?
Thanks!
I wonder if it's worth passing primitive single values like int, float, double or char by pointer?
What are you trying to accomplish? Do you want to be able to write to the passed in value? Or do you just need to use it? If you want to write to it, the idiomatic way is to pass by reference. If you don't need to write to it, you're best avoiding any risk that you'll write to it accidentally and pass by value. Pass by value will make a copy of the variable for local use. (as an aside, if you don't want to make a copy AND want some level of safety, you can pass by const reference)
But if you would simply pass everything by pointer, is this making the program slower?
Difficult to say. Depends on a lot of things. In both pass by value and pass by reference (or pointer) your making a new primitive type. In pass by value, you're making a copy. In pass by reference/pointer you're passing an address to the original. In the latter case, however, you're requiring an extra fetch of memory that may or may not be cached. Its very difficult to say 100% without measuring it.
That all being said, I doubt the difference is even noticeable. The compiler may be able to optimize out the copy in many pass-by-value cases, as indicated in this article. (thanks Space C0wb0y).
Should you always just pass arrays as pointer?
From this.
In C++ it is not possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address.
To pass an array:
int foo(int bar[], unsigned int length)
{
// do stuff with bar but don't go past length
}
I'd recommended avoiding arrays and using std::vector which has more easily understood copy semantics.
It's probably not worth passing primitive values by pointer if your concern is speed -- you then have the overhead of the "indirection" to access the value.
However, pointers often are the "width of the bus", meaning the processor can send the whole value at once, and not "shift" values to send-down-the-bus. So, it is possible pointers are transferred on the bus faster than smaller types (like char). That's why the old Cray computers used to make their char values 32 bits (the width of the bus at that time).
When dealing with large objects (such as classes or arrays) passing pointer is faster than copying the whole object onto the stack. This applies to OOP for example
Look in your favorite C++ textbook for a discussion of "output parameters".
Some advantages of using a pointer for output parameters instead of a reference are:
No surprising behavior, no action at a distance, the semantics are clear at the call site as well as the caller.
Compatibility with C (which your question title suggests is important)
Usable by other languages, functions exported from a shared library or DLL should not use C++-only features such as references.
You should rarely have to pass anything by pointer. If you need to modify the value of the parameter, or want to prevent a copy, pass by reference, otherwise pass by value.
Note that preventing a copy can also be done by copy-elision, so you have to be very careful not to fall into the trap of premature optimization. This can actually make your code slower.
There's is no real answer to your question except few rules that I tend to bare in mind:
char is 8 bytes and a pointer is 4 bytes so never pass a single char as a pointer.
after things like int and float are the same size as a pointer but a pointer has to be referenced so that technically takes more time
if we go to the pentium i386 assembler:
loading the value in a register of a parameter "a" in C which is an int:
movl 8(%ebp),%eax
the same thing but passed as a pointer:
movl 8(%ebp),%eax
movl (%eax),%eax
Having to dereference the pointer takes another memory operation so theorically (not sure it is in real life) passing pointers is longer...
After there's the memory issue. If you want to code effectively everything composed type (class,structure,arrays...) has to be passed by pointer.
Just imagine doing a recursive function with a type of 16bytes that is passed by copy for 1000 calls that makes 16000 bytes in the stack (you don't really want that do you ? :) )
So to make it short and clear: Look at the size of your type if it's bigger than a pointer pass it by pointer else pass it by copy...
Pass primitive types by value and objects as const references. Avoid pointers as much as you can. Dereferencing pointers have some overhead and it clutters code. Compare the two versions of the factorial function below:
// which version of factorial is shorter and easy to use?
int factorial_1 (int* number)
{
if ((*number) <= 1)
return 1;
int tmp = (*number) - 1;
return (*number) * factorial_1 (&tmp);
}
// Usage:
int r = 10;
factorial_1 (&r); // => 3628800
int factorial_2 (int number)
{
return (number <= 1) ? 1 : (number * factorial_2 (number - 1));
}
// Usage:
// No need for the temporary variable to hold the argument.
factorial_1 (10); // => 3628800
Debugging becomes hard, as you cannot say when and where the value of an object could change:
int a = 10;
// f cound modify a, you cannot guarantee g that a is still 10.
f (&a);
g (&a);
Prefer the vector class over arrays. It can grow and shrink as needed and keeps track of its size. The way vector elements are accessed is compatible with arrays:
int add_all (const std::vector<int>& vec)
{
size_t sz = vec.size ();
int sum = 0;
for (size_t i = 0; i < sz; ++i)
sum += vec[i];
}
NO, the only time you'd pass a non-const reference is if the function requires an output parameter.