प्रतिलिपि सूची प्रारंभ? यह संकलन क्यों करता है?


13

मैं Microsoft Visual Studio समुदाय 2019, V16.5.2 का उपयोग कर रहा हूं। मैं सूची आरंभीकरण का परीक्षण करना चाहता हूं

कृपया निम्नलिखित परीक्षण कार्यक्रम देखें:

#include <string>

void foo(std::string str) {}

int main() {

    foo( {"str1", "str2"} );

    return 0;
}

यह त्रुटि और चेतावनी के बिना संकलित करता है। क्यों?

यह रनटाइम त्रुटि देता है: Expression: Transposed pointer range

क्या कोई समझा सकता है कि यहाँ क्या हो रहा है?


संपादित करें।

मैंने कोड को अलग कर दिया और इसे डिबगर में चला दिया

    foo( {"str1", "str2"} );
00F739A8  sub         esp,1Ch  
00F739AB  mov         esi,esp  
00F739AD  mov         dword ptr [ebp-0C8h],esp  
00F739B3  lea         ecx,[ebp-0D1h]  
00F739B9  call        std::allocator<char>::allocator<char> (0F7136Bh)  
00F739BE  push        eax  
00F739BF  push        offset string "str2" (0F84DB8h)  
00F739C4  push        offset string "str1" (0F84E2Ch)  
00F739C9  mov         ecx,esi  
00F739CB  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> ><char const *,0> (0F71569h)  
00F739D0  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (0F71843h)  
00F739D5  add         esp,1Ch  

यह कंस्ट्रक्टर को पहली कॉल पर क्रैश कर देता है?


मुझे आपका संपादन समझ में नहीं आ रहा है, लेकिन ऐसा लग रहा है कि शायद यह एक अलग प्रश्न है, इसलिए शायद आपको इसके लिए एक नया प्रश्न पोस्ट करने की आवश्यकता है?
मूंग बतख

जवाबों:


16

std::stringएक टेम्पलेट कंस्ट्रक्टर है जो एक स्टार्ट / एंड इट्रेटर जोड़ी से एक स्ट्रिंग बनाता है। सी ++ में शाब्दिक स्ट्रिंग const char*एस के लिए नीचे आते हैं । और संकेत iterators हैं। इसलिए, सूची आरंभीकरण ने आरंभ / अंत जोड़ी निर्माता को चुना।

आपको एक रनटाइम त्रुटि मिली क्योंकि दो पॉइंटर्स वास्तव में एक वैध सीमा नहीं बनाते हैं, जिसे संकलन-समय (आम तौर पर) पर निर्धारित नहीं किया जा सकता है।


मै समझता हुँ। रेंज कंस्ट्रक्टर। मैंने कोड को डिसाइड किया और डीबग किया। यह कंस्ट्रक्टर को पहली कॉल में क्रैश कर देता है। मुझे समझ नहीं आ रहा है <char const *,0>। क्या कोई इसे समझा सकता है?
आर्मिन मोंटेगैन

THAT का मतलब है कि यह template< InputIt > (InputIt first, InputIt last,...)कंस्ट्रक्टर को बुला रहा है जहां टेम्पलेट पैरामीटर iterहै const char*.... और जाहिर है कि आपके कार्यान्वयन में किसी कारण से दूसरा पूर्णांक पैरामीटर है?
मूंग बतख

@ArminMontigny: बताइए क्या? डिस्सैम्फ्रेश अनिवार्य रूप से अप्रासंगिक है। आपके कोड को सिंटैक्टिक रूप से मान्य माना जाता है, लेकिन यह पुनरावृत्तियों की वैध श्रेणी नहीं होने के कारण अपरिभाषित व्यवहार देता है। आपको यह समझने की आवश्यकता नहीं है कि आपका कोड गैर-कार्यात्मक क्यों है।
निकोल बोलस

8

std::string के रूप में एक रचनाकार अधिभार है

template< class InputIt >
basic_string( InputIt first, InputIt last,
              const Allocator& alloc = Allocator() );

और यह कहा जाता है क्योंकि "str1"और "str2"क्षय है const char*और const char*एक स्वीकार्य पुनरावृत्ति प्रकार है।

आपको एक क्रैश मिल जाता है क्योंकि "इटेरियर रेंज" जो आपने फ़ंक्शन को पास किया है वह अमान्य है।


धन्यवाद, समझ गया। +1। कृपया संपादन देखें।
आर्मिन मोंटेगैन

7

कि std :: string (6.) के पुनरावृत्तियों के साथ निर्माणकर्ता का उपयोग करें ।

template< class InputIt >
constexpr basic_string( InputIt first, InputIt last,
                        const Allocator& alloc = Allocator() );

[ InputIt= const char*] के साथ।

फिर आपके पास UB है क्योंकि सीमा {"str1", "str2"}अमान्य है।


धन्यवाद, समझ गया। +1। कृपया संपादन देखें।
आर्मिन मोंटेगैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.