2016-07-29 67 views
6

有没有办法来阻止gcc中的std::function动态分配内存的大功能对象?从gcc分配内存或增加阈值防止std ::函数

我本来期望下面的代码没有动态分配工作:

#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; 
} 

但是它分配24个字节。据我所知,这是因为指向方法的指针需要16个字节,指向类实例的指针需要8个字节。这似乎是比函数对象可用的内部内存大或B是一个普通的错误。

我想知道是否有任何方法可以绕过这种类型的行为,而无需更改std::function的签名或创建大量附加包装代码。

+0

标准规定_I实现被鼓励避免为小的可调用对象使用动态分配的内存,例如,其中f是只持有指向对象和成员函数pointer_的指针或引用的对象。编译器尽其所能。如果它不符合你的需求,那么... – skypjack

+0

clang + libC++没有在你的例子中分配任何内存(http://coliru.stacked-crooked.com/a/52505806440111db) – Praetorian

回答

6

不幸的是GCC的function只有一个指向内部存储的成员函数的指针空间,所以你的bind表达式的结果不适合。

可以使用lambda表达式虽然代替:

std::function<int()> f = [&]{ return testor.getValue(); }; 

这仅需要用于包含到testor基准(这是一个指针,指向件的大小的一半的闭合型的空间,和的第三绑定结果的大小),并且GCC定义了关闭,因此它可以存储在std::function中。

+0

@ T.C。我的确如此 - 这就是我测试的结果。但不是我出于某种原因在此输入的内容。谢谢。 –

0

查看libstdC++(GCC的默认C++库)的特殊皮肤爬行functional标题,发现实际上不可能避免使用其当前实现的堆分配。它似乎有一个特殊的经理和调用者成员,它是堆分配的,并且它是班级工作所必需的。如果你真的想看看来源,here you go,但那里肯定有黑色的艺术和巫术。

标题中有一些功能意味着计划在custom allocators中传递,但目前它们似乎没有实现。

与此同时,您可以尝试Boost.function

+0

它会避免堆分配if '__stored_locally'条件成立。不幸的是,对于大于指向成员函数的指针的任何内容都是错误的,所以不能在本地存储该指针和指向对象的指针。 –