Is there any way to prevent std::function
in gcc from dynamically allocating memory for larger function objects?
I would have expected the following code to work without dynamic allocation:
#include <functional>
#include <iostream>
// replace operator new and delete to log allocations
void* operator new (std::size_t n) {
std::cout << "Allocating " << n << " bytes" << std::endl;
return malloc(n);
}
void operator delete(void* p) throw() {
free(p);
}
class TestPlate
{
private:
int value;
public:
int getValue(){ return value; }
void setValue(int newValue) { value = newValue; }
int doStuff(const std::function<int()>& stuff) { return stuff(); }
};
int main()
{
TestPlate testor;
testor.setValue(15);
const std::function<int()>& func = std::bind(&TestPlate::getValue, &testor);
std::cout << testor.doStuff(func) << std::endl;
testor.setValue(25);
std::cout << testor.doStuff(func) << std::endl;
}
However it allocates 24 bytes. As far as I am able to tell this is because the pointer to method requires 16 bytes and the pointer to the class instance another 8 bytes. This seems to be either A larger than the internal memory available to the function object or B a plain bug.
I was wondering whether there are is any way to circumvent this type of behavior without changing the signature of the std::function
or creating a lot of additional wrapper code.
The reason for the dynamic memory allocation is that std::function is generic and has no idea how much data you captured, but that captured data has to exist inside of a std::function and also has to be able to be copied as a std::function is moved around or copied to other locations.
Use the malloc() function to allocate memory in designated blocks and the new function to create memory in the free store (heap). To reallocate memory, the realloc() function is used. When finished, always include a free() function in order to free up the memory. If you used new(), use delete() to free up the memory.
Heap memory is slightly slower to be read from and written to, because one has to use pointers to access memory on the heap. We will talk about pointers shortly. Unlike the stack, variables created on the heap are accessible by any function, anywhere in your program.
Unfortunately GCC's function
only has space for a pointer to member function stored internally, so the result of your bind expression doesn't fit.
You can use a lambda expression instead though:
std::function<int()> f = [&]{ return testor.getValue(); };
This only requires space for a closure type containing a reference to testor
(which is half the size of a pointer to member, and a third of the size of the bind result), and GCC defines that closure so it can be stored in a std::function
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With