एसटीडी के अंदर प्रारंभिक सूची :: जोड़ी


26

यह कोड:

#include <iostream>
#include <string>

std::pair<std::initializer_list<std::string>, int> groups{ { "A", "B" }, 0 };

int main()
{
    for (const auto& i : groups.first)
    {
        std::cout << i << '\n';
    }
    return 0;
}

संकलित करता है, लेकिन segfault लौटाता है। क्यों?

8.3.0 gcc पर और ऑनलाइन कंपाइलरों पर परीक्षण किया गया।


1
सुविधा के लिए: Godbolt लिंक के साथ और बिना std::pair
मैक्स लैंगहॉफ

जवाबों:


24

std::initializer_listसंग्रहीत करने के लिए नहीं है, यह सिर्फ ... अच्छी तरह से आरंभीकरण के लिए है। आंतरिक रूप से यह केवल एक संकेतक को पहले तत्व और आकार में संग्रहीत करता है। आपके कोड में std::stringवस्तुएं अस्थायी हैं और initializer_listन तो उनका स्वामित्व लेता है, न तो उनके जीवन का विस्तार करता है, न ही उन्हें कॉपी करता है (क्योंकि यह कंटेनर नहीं है) इसलिए वे निर्माण के तुरंत बाद दायरे से बाहर चले जाते हैं, लेकिन आपका initializer_listअभी भी उनके लिए एक संकेतक है। यही कारण है कि आपको विभाजन दोष मिलता है।

भंडारण के लिए आपको कंटेनर का उपयोग करना चाहिए, जैसे std::vectorया std::array


यह मुझे परेशान करता है कि यह बाध्यकारी है। मूर्खतापूर्ण भाषा :(
लाइटवेट दौड़ में कक्षा

1
@LightnessRaceswithMonica मेरे पास बहुत से गोमांस हैं initializer_list। मूव-ओनली ऑब्जेक्ट्स का उपयोग करना संभव नहीं है, इसलिए आप उदाहरण के लिए unique_ptr के वेक्टर के साथ सूची इनिट का उपयोग नहीं कर सकते। का आकार initializer_listएक संकलन-समय स्थिर नहीं है। और तथ्य यह है कि std::vector<int>(3)और std::vector<int>{3}पूरी तरह से अलग चीजें करते हैं। मुझे दुखी करता है :(
बोल्व


3

मैं अभी थोड़ा और विवरण जोड़ूंगा। एक अंतर्निहित सरणी std::initializer_listअस्थायी रूप से इसी तरह का व्यवहार करती है। निम्नलिखित वर्ग पर विचार करें:

struct X
{
   X(int i) { std::cerr << "ctor\n"; }
   ~X() { std::cerr << "dtor\n"; }
};

और निम्नलिखित कोड में इसका उपयोग:

std::pair<const X&, int> p(1, 2);
std::cerr << "barrier\n";

यह प्रिंट करता है

ctor
dtor
barrier

चूंकि पहली पंक्ति में, प्रकार Xका एक अस्थायी उदाहरण बनाया जाता है (निर्माणकर्ता से परिवर्तित करके 1) और साथ ही नष्ट हो जाता है। में संग्रहीत संदर्भ pतो झूल रहा है।

जैसे std::initializer_list, यदि आप इसे इस तरह से उपयोग करते हैं:

{
   std::initializer_list<X> l { 1, 2 };
   std::cerr << "barrier\n";
}

तब तक, अंतर्निहित (अस्थायी) सरणी लंबे समय से lबाहर निकलती है। इसलिए, आउटपुट है:

ctor
ctor
barrier
dtor
dtor

हालाँकि, यदि आप स्विच करते हैं

std::pair<std::initializer_list<X>, int> l { {1}, 2 };
std::cerr << "barrier\n";

आउटपुट फिर से है

ctor
dtor
barrier

चूंकि अंतर्निहित (अस्थायी) सरणी केवल पहली पंक्ति में मौजूद है। तत्पश्चात के तत्वों को पॉइंफ्रेंसिंग को अपरिभाषित करने के lपरिणामस्वरूप अपरिभाषित व्यवहार होता है।

लाइव डेमो यहाँ है

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