क्या C ++ 20 में बाद के रनटाइम निर्णय के आधार पर अलग-अलग निहित वस्तुएं हो सकती हैं?


11

यह प्रश्न P0593 के नवीनतम C ++ 20 मसौदे को जोड़ने के लिए संदर्भित करता है ।

यहाँ मेरा उदाहरण है:

#include <cstdlib>
#include <cstdio>

void foo(void *p)
{
    if ( std::getchar() == 'i' )
    {
        *(int *)p = 2;
        std::printf("%d\n", *(int *)p);
    }
    else
    {
        *(float *)p = 2;
        std::printf("%f\n", *(float *)p);
    }
}

int main()
{
    void *a = std::malloc( sizeof(int) + sizeof(float) );
    if ( !a ) return EXIT_FAILURE;

    foo(a);
    // foo(a);    [2]
}

क्या यह कोड नवीनतम ड्राफ्ट के तहत सभी इनपुट के लिए अच्छी तरह से परिभाषित है?

P0593 में व्यक्त किया गया औचित्य यह स्पष्ट करता है कि [2]यदि दो उपयोगकर्ता इनपुट आइटम अलग-अलग हैं, तो सख्ती से अलियासिंग उल्लंघन के कारण अपरिभाषित व्यवहार को अपरिभाषित किया जाएगा। अंतर्निहित वस्तु निर्माण के बिंदु पर सिर्फ एक बार होने वाला है malloc; इसमें असाइनमेंट स्टेटमेंट द्वारा ट्रिगर नहीं किया गया है foo

कार्यक्रम के किसी भी वास्तविक रन के लिए, निहित वस्तुओं के अनिर्दिष्ट सेट का एक सदस्य मौजूद है जो कार्यक्रम को अच्छी तरह से परिभाषित करेगा। लेकिन मेरे लिए यह स्पष्ट नहीं है कि निहित वस्तु के निर्माण का विकल्प [intro.object] / 10 में उल्लिखित mallocहै या नहीं; या क्या निर्णय "समय यात्रा" कर सकता है।

एक ही मुद्दा एक प्रोग्राम के लिए उत्पन्न हो सकता है जो एक बाइनरी बूँद को बफ़र में पढ़ता है और फिर इसे एक्सेस करने का एक रनटाइम निर्णय लेता है (उदाहरण के लिए डिसेरिएलाइज़ेशन; और हेडर हमें बताता है कि क्या फ़्लोट या इंट आ रहा है)।

जवाबों:


9

अंतर्निहित वस्तु निर्माण के बिंदु पर सिर्फ एक बार होने वाला है malloc; इसमें असाइनमेंट स्टेटमेंट द्वारा ट्रिगर नहीं किया गया है foo

यह प्रासंगिक नहीं है। कौन सी वस्तु किस वस्तु से निर्मित होती है। मानक का कहना है कि जो वस्तु बनाई जाती है, वह एक ऐसी चीज है जो यूबी को अच्छी तरह से परिभाषित कोड में बनाती है:

यह ऑपरेशन अनुमानित रूप से शून्य या अधिक वस्तुओं के आजीवन (अंतर्निहित मूलभूत प्रकार [[basic.types]) को उसके निर्दिष्ट क्षेत्र में संग्रहीत करने का कार्य शुरू करता है यदि ऐसा करने से कार्यक्रम में परिभाषित व्यवहार होता है।

व्यवहार अंततः रनटाइम निष्पादन पर आधारित है, न कि स्थैतिक विश्लेषण। इसलिए आपको केवल कार्यक्रम के निष्पादन का पालन करने की आवश्यकता है जब तक कि आप एक ऐसे मामले में भाग नहीं लेते हैं जहां व्यवहार को परिभाषित नहीं किया जाएगा, फिर भी परिभाषित किया जाएगा यदि किसी प्रकार की वस्तु को उस भंडारण में बनाया गया था जब ऑपरेशन के समय प्रश्न में।

तो सृजन का स्थान हमेशा "ऑपरेशन" होता है, लेकिन जो भी बनाया जाता है उसका निर्धारण इस बात पर आधारित होता है कि स्मृति रनटाइम पर कैसे उपयोग की जाती है (अर्थात: व्यवहार)।


2
स्पष्ट होने के लिए, आप कह रहे हैं कि मेरा कोड अच्छी तरह से परिभाषित है?
एम एम

2
@MM: यह सही है।
निकोल बोलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.