2016-07-29 7 views
6

बढ़ाने से जीसीसी में std :: फ़ंक्शन को रोकें क्या gcc में std::function को बड़ी फ़ंक्शन ऑब्जेक्ट्स के लिए गतिशील रूप से आवंटित करने से रोकने का कोई तरीका है?स्मृति को आवंटित करने या थ्रेसहोल्ड

मैं निम्नलिखित कोड गतिशील आवंटन के बिना काम करने की उम्मीद है |:

#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 अन्य बाइट्स की आवश्यकता होती है। ऐसा लगता है कि फ़ंक्शन ऑब्जेक्ट या बी को सादा बग के लिए उपलब्ध आंतरिक मेमोरी से बड़ा बड़ा लगता है।

मैं सोच रहा था कि std::function के हस्ताक्षर को बदले बिना या अतिरिक्त अतिरिक्त रैपर कोड बनाने के बिना इस प्रकार के व्यवहार को रोकने के लिए कोई तरीका है या नहीं।

+0

मानक राज्यों कि _ कार्यान्वयन को छोटे कॉल करने योग्य वस्तुओं के लिए गतिशील रूप से आवंटित स्मृति के उपयोग से बचने के लिए प्रोत्साहित किया जाता है, उदाहरण के लिए, जहां एफ एक वस्तु है जो किसी ऑब्जेक्ट को संदर्भित करता है या किसी सदस्य फ़ंक्शन पॉइंटर_ को संदर्भित करता है। कंपाइलर्स अपना सर्वश्रेष्ठ प्रदर्शन करते हैं। यदि यह आपकी आवश्यकताओं के अनुरूप नहीं है, तो ... – skypjack

+0

क्लैंग + libC++ आपके उदाहरण में किसी भी स्मृति को आवंटित नहीं कर रहा है (http://coliru.stacked-crooked.com/a/52505806440111db) – Praetorian

उत्तर

6

दुर्भाग्य से जीसीसी के function में केवल आंतरिक रूप से संग्रहीत सदस्य फ़ंक्शन के लिए पॉइंटर के लिए स्थान है, इसलिए आपकी बाइंड अभिव्यक्ति का परिणाम फिट नहीं है।

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

यह केवल (testor के लिए एक संदर्भ जो सदस्य के लिए सूचक के आधे आकार है जिसमें एक बंद प्रकार के लिए स्थान की आवश्यकता होती है, और का एक तिहाई:

आप एक लैम्ब्डा अभिव्यक्ति के बजाय यद्यपि उपयोग कर सकते हैं बाध्य परिणाम का आकार), और जीसीसी उस बंद को परिभाषित करता है ताकि इसे std::function में संग्रहीत किया जा सके।

+0

@ टी.सी. वास्तव में मैं करता हूं - और यही वह है जो मैंने परीक्षण किया था। लेकिन कुछ कारणों से मैंने यहां टाइप नहीं किया। धन्यवाद। –

0

libstdC++ (जीसीसी की डिफ़ॉल्ट सी ++ लाइब्रेरी) के असाधारण त्वचा-क्रॉलिंग functional शीर्षलेख के माध्यम से देखकर, मुझे पता चला कि वर्तमान में कार्यान्वयन के साथ ढेर आवंटन से बचना वास्तव में असंभव है। ऐसा लगता है कि एक विशेष प्रबंधक और आवेदक सदस्य है जो ढेर-आवंटित है, और कक्षा के काम के लिए यह आवश्यक है। यदि आप वास्तव में स्रोत, here you go पर देखना चाहते हैं, लेकिन वहां निश्चित रूप से काले कला और जादूगर चल रहे हैं।

शीर्षलेख में कुछ कार्यक्षमता है जो custom allocators में गुजरने का तात्पर्य है, लेकिन इस समय उन्हें लागू नहीं किया जा रहा है।

इस बीच, आप Boost.function को आजमा सकते हैं।

+0

यह ढेर आवंटन से बच जाएगा '__stored_locally' स्थिति सत्य है। दुर्भाग्यवश यह सदस्य फ़ंक्शन के सूचक के मुकाबले किसी भी चीज़ के लिए गलत है, इसलिए उसे स्थानीय रूप से किसी ऑब्जेक्ट पर पॉइंटर स्टोर नहीं किया जा सकता है। –

संबंधित मुद्दे