I have an array of function pointers and I want to assign simple dummy functions.
The first thing that came to my mind was using lambda. That worked pretty well. The only thing that surprised me was the fact that I get different pointer addresses when I assign them one by one, but get identical addresses when I do it in a loop.
#include <iostream>
int main()
{
int (*ptrArr[6])(void);
int size = sizeof(ptrArr)/sizeof(void*);
// results in three different pointer addresses
ptrArr[0] = [](){return 0;};
ptrArr[1] = [](){return 0;};
ptrArr[2] = [](){return 0;};
// results in three identical pointer addresses
for(int i = 3; i < size; i++)
{
ptrArr[i] = [](){return 0;};
}
for(int i = 0; i < 6; i++)
{
std::cout << (void*)ptrArr[i] << std::endl;
}
return 0;
}
Output:
00E9F810
00E9F840
00E9F870
00E9F8A0
00E9F8A0
00E9F8A0
Is there a way to get different instances of the dummy functions using the loop?
I also tried some constructions using std::function<>
, but didn't get it assigned to the function pointers.
I have an array of function pointers and I want to assign simple dummy functions.
The first thing that came to my mind was using lambda. That worked pretty well. The only thing that surprised me was the fact that I get different pointer addresses when I assign them one by one, but get identical addresses when I do it in a loop.
#include <iostream>
int main()
{
int (*ptrArr[6])(void);
int size = sizeof(ptrArr)/sizeof(void*);
// results in three different pointer addresses
ptrArr[0] = [](){return 0;};
ptrArr[1] = [](){return 0;};
ptrArr[2] = [](){return 0;};
// results in three identical pointer addresses
for(int i = 3; i < size; i++)
{
ptrArr[i] = [](){return 0;};
}
for(int i = 0; i < 6; i++)
{
std::cout << (void*)ptrArr[i] << std::endl;
}
return 0;
}
Output:
00E9F810
00E9F840
00E9F870
00E9F8A0
00E9F8A0
00E9F8A0
Is there a way to get different instances of the dummy functions using the loop?
I also tried some constructions using std::function<>
, but didn't get it assigned to the function pointers.
3 Answers
Reset to default 5you can use a function template to generate multiple dummy unique functions.
#include <iostream>
#include <array>
template <size_t N>
int func() { return N; }
int main()
{
constexpr size_t functions_count = 6;
using func_type = int (*)(void);
static constexpr auto ptrArr =
[]<size_t...Ints>(std::integer_sequence<std::size_t, Ints...>)
{
return std::array<func_type,sizeof...(Ints)>{&func<Ints>...};
}(std::make_integer_sequence<size_t,functions_count>{});
for(int i = 0; i < functions_count; i++)
{
std::cout << (void*)ptrArr[i] << std::endl;
}
return 0;
}
0x58e668ea51d0
0x58e668ea51e0
0x58e668ea51f0
0x58e668ea5200
0x58e668ea5210
0x58e668ea5220
online demo
the size needs to be known at compile time.
i think the variadic lambda is C++20, for lower versions use a free function instead. demo
The reason the pointers sometimes are equal and sometimes not becomes much clearer if you replace the lambda expressions with free functions :
#include <iostream>
int fooA() { return 0; };
int fooB() { return 0; };
int fooC() { return 0; };
int fooD() { return 0; };
int main()
{
int (*ptrArr[6])(void);
int size = sizeof(ptrArr)/sizeof(*ptrArr);
// results in three different pointer addresses
ptrArr[0] = fooA;
ptrArr[1] = fooB;
ptrArr[2] = fooC;
// results in three identical pointer addresses
for(int i = 3; i < size; i++)
{
ptrArr[i] = fooD;
}
for(int i = 0; i < 6; i++)
{
std::cout << (void*)ptrArr[i] << std::endl;
}
return 0;
}
Each time you write the expression [](){return 0;};
you create a new hidden function, then for each loop iteration your function pointer is assigned to that same function. Even if you loop over that lambda expression multiple times, it is only defined once. In the same way getting the address of fooD
repeatedly should always give the same pointer, getting the address of one [](){return 0;}
will also always give the same pointer.
A lambda creates a distinct class type with an overloaded operator()
. A non-capturing lambda is convertible to a function pointer that invokes the same code as that operator.
In your first use-case, you are creating 3 separate lambda instances, and they are remaining in scope until main()
exits. That is 3 separate objects in memory at the same time. The compiler may recognize that they are doing the same thing and optimize them into a single instance, but that is unlikely. So, you end up seeing 3 separate addresses being used.
In your second use-case, you are creating and destroying a single lambda instance on every loop iteration. There is only 1 object in memory at a time, so the compiler is free to reuse the same memory for each object.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744954923a4603135.html
int size = sizeof(ptrArr)/sizeof(void*);
-- there is no guarantee thatvoid*
is the same size as a pointer to function. The usual way to do this would besizeof(ptrArr)/sizeof(*ptrArr)
. But you already know the size of your array: it's 6. If you don't throw away that information you don't have to figure out how to get it back. – Pete Becker Commented Mar 6 at 19:19std::size
. – user4581301 Commented Mar 6 at 19:20