जीसीसी के साथ सी ++ 11 के तहत संकलित निम्नलिखित कोड पर विचार करें:

#include <cstdio>
#include <functional>
#include <unordered_map>
using namespace std;
using namespace std::placeholders;

class Box
{
    char* box;

public:
    Box(): box(new char[128]) {}
    ~Box()
    {
        delete[] this->box;
    }
    void example(int a, int b)
    {
        printf("%d %d", a, b);
    }
};

Box box;
unordered_map<char, function<void(int, int)>> methods = {
    {'a', bind(&Box::example, box, _1, 8)}
};

int main()
{
    fputs("Main called.", stdout);
    return 0;
}

प्रोग्राम को त्रुटियों के बिना बनाया जा सकता है लेकिन इसे लॉन्च करने के प्रयास को अनदेखा कर दिया जाता है या विफलता में परिणाम होता है।

विंडोज 10 पर, कमांड प्रॉम्प्ट के माध्यम से परिणामी exe फ़ाइल को लॉन्च करना बिना किसी स्पष्टीकरण के एक रिक्त रेखा को प्रिंट करता है, भले ही प्रोग्राम को Main called. आउटपुट करना चाहिए।

वीएस कोड के एकीकृत टर्मिनल में इसे चलाने पर मुझे कुछ हद तक बेहतर त्रुटि संदेश मिलता है:

The terminal process "C:\WINDOWS\System32\cmd.exe /d /c {path to exe file} failed to launch (exit code: 3221226356).

जब मैं बॉक्स परिभाषा को एक में बदलता हूं जो बॉक्स सदस्य के लिए पॉइंटर का उपयोग नहीं करता है तो यह काम करता है:

class Box
{
    char box[128];

public:
    void example(int a, int b)
    {
        printf("%d %d", a, b);
    }
};

क्या दिया?

1
sanitizedUser 18 सितंबर 2020, 03:42

1 उत्तर

सबसे बढ़िया उत्तर

यह सी ++ के कई रहस्यमय पहलुओं का संयोजन है:

unordered_map<char, function<void(int, int)>> methods = {
    {'a', bind(&Box::example, box, _1, 8)}
};

यदि आप इसे इसमें बदलते हैं:

unordered_map<char, function<void(int, int)>> methods = {
    {'a', bind(&Box::example, &box, _1, 8)}
};

कोड अभी भी संकलित होना चाहिए, और यह त्रुटियों के बिना चलेगा। जीसीसी 10 के साथ सत्यापित।

आपकी कक्षा Box तीन के नियम का उल्लंघन करती है। यदि कोई Box ऑब्जेक्ट कॉपी-निर्मित हो जाता है, तो एक ही पॉइंटर के साथ एक Box ऑब्जेक्ट की प्रतियां होंगी, और जब दोनों नष्ट हो जाएंगे, तो delete करने का प्रयास किया जाएगा एक ही सूचक कई बार। हिलैरिटी आती है।

तो यह पहला कारक है जिसने आपकी समस्या को उठाया: आपकी कक्षा नियम 3 का अनुपालन नहीं कर रही थी।

दूसरा मुद्दा यह है कि std::bind काफी बहुमुखी है और इसमें कई ओवरलोड हैं। आपके प्रोग्राम में आपके द्वारा उपयोग किया गया अधिभार प्रभावी रूप से उबलता है (इसके आंतरिक कामकाज के हिस्से के रूप में) box ऑब्जेक्ट की एक आंतरिक प्रतिलिपि बनाई जाती है, जिससे नियम 3 उल्लंघन होता है।

लेकिन std::bind बाउंड मेथड के साथ ऑब्जेक्ट के पॉइंटर का उपयोग करके यहां भी काम कर सकता है, और इससे इसकी एक कॉपी बनाने की आवश्यकता से बचा जाता है।

1
Sam Varshavchik 18 सितंबर 2020, 03:57