I'm trying to understand the overhead of pass object by value as a function parameter in C++/Linux/x86-64 platform.
The experimental code I used for the exploration is posted below and on godbolt.org: https://godbolt.org/z/r9Yfv4
Assume the function is unary. What I observed is:
- If the parameter object is a 8 bytes in size, it will be put in RDI.
- If the parameter is 16 bytes in size (contain two sub-object each 8 bytes), the two sub-objects will be put in to RDI and RSI.
- If the parameter is bigger than 16 bytes, it will be passed via stack.
I only consider integral types and pointers and the composition types of these basic types. I know passing floats/doubles is different.
The size of std::function
is 32 bytes (GCC/Linux implementation, long + long + pointer + pointer = 32 bytes.). So passing std::function
by value should look like pass struct Person4
defined in my code. But the output assembly shows that pass std::function
is very different from pass struct Person3
. It looks like std::function is passed via a pointer, am I right? Why there is such a difference?
#include <functional>
struct Person0 {
long name;
};
long GetName(Person0 p) {
return p.name;
}
struct Person1 {
long name;
long age;
};
long GetName(Person1 p) {
return p.name;
}
struct Person2 {
long name;
long age;
long height;
};
long GetName(Person2 p) {
return p.name;
}
struct Person3 {
long name;
long age;
long height;
long weight;
};
long GetName(Person3 p) {
return p.name + sizeof(p);
}
long Invoke(std::function<long(long)> f) {
return f(20) + sizeof(f);
}
int main() {
Person3 p;
p.name = 13;
p.age = 23;
p.height = 33;
p.weight = 43;
long n = GetName(p);
std::function<long(long)> ff;
Invoke(ff);
return 0;
}
struct Person4
but there is none in your code. – Fikestd::function
's type erasure that makes the compiler do that? (just adding to the confusion perhaps - intersting question) – Aspersion