2013-03-29 13 views
5

निम्नलिखित कार्यक्रम दुर्घटनाओं:विभाजन गलती जब segmention गलती के साथ आगे बढ़ std :: वेक्टर

#include <iostream> 
#include <vector> 

using namespace std; 

struct data 
{ 
    data() : a(random()), b(random()), v({random(), random(), random()}) {} 
    data(data&& m) noexcept : a(m.a), b(m.b), v(std::move(m.v)) { } 

    long int a; 
    long int b; 
    std::vector<long int> v; 
}; 

data&& randomize() 
{ 
    srandom(time(0)); 
    data d; 
    d.a = random(); 
    return std::move(d); 
} 

int main(int argc, char** argv) 
{ 
    data d = randomize(); 
    cout << d.a << " " << d.b << endl; 
    return 0; 
} 

कोड जी ++ संस्करण 4.7.2 (Debian 4.7.2-5) के साथ संकलित किया गया है:

g++ -std=c++11 -g test.cpp 

मैं क्या गलत कर रहा हूँ? समस्या std :: वेक्टर चालक कन्स्ट्रक्टर में प्रतीत होती है, क्योंकि सबकुछ इसके बिना ठीक काम करता है। ऐसा लगता है कि फ़ंक्शन समाप्त होने पर यादृच्छिक() को नष्ट कर दिया जाता है, लेकिन इसे मुख्य रूप से डेटा ऑब्जेक्ट में स्थानांतरित नहीं किया जाना चाहिए?

+3

ध्यान दें कि यहां * रावल्यू * संदर्भ वापस करने की आवश्यकता नहीं है (भले ही यह स्थानीय स्वचालित चर के संदर्भ को वापस करने के लिए मान्य हो)। यदि संभव हो तो फ़ंक्शन रिटर्न मान हमेशा स्थानांतरित हो जाते हैं। –

उत्तर

13

यह समारोह:

data&& randomize() 
{ 
    // ... 
    data d 
    // ... 
    return std::move(d); 
} 

एक स्थानीय वस्तु जो जब नष्ट हो कॉल रिटर्न जा रहा है करने के लिए एक संदर्भ देता है। इसलिए, आपके प्रोग्राम में अपरिभाषित व्यवहार है। इसलिए, लौटे संदर्भ समय data की चाल निर्माता यहाँ शुरू हो जाती है द्वारा झूलते हो जाएगा:

data d = randomize(); 

आप प्रकार data के मूल्य लौटना चाहिए, और आप स्पष्ट std::move() नहीं आह्वान करना चाहिए:

data randomize() 
{ 
    // ... 
    data d 
    // ... 
    return d; 
} 

इस तरह, आप संकलक को (Named) Return Value Optimization करने का मौका भी देंगे, जिसके परिणामस्वरूप चालक कन्स्ट्रक्टर को कोई कॉल नहीं होगा।

+0

आपके उत्तर के लिए धन्यवाद! लेकिन क्या यह अनुकूलन हमेशा जीसीसी द्वारा किया जाएगा, या कुछ अपवाद हैं? –

+0

@PavelDavydov: आपका स्वागत है :) यह निर्णय लेने के लिए पूरी तरह से संकलक तक है, और आपको इस धारणा पर भरोसा नहीं करना चाहिए कि यह elision है या नहीं किया गया है। आप बस नहीं बता सकते हैं। इस मामले में, हालांकि, यह होगा कि पर्याप्त उच्च अनुकूलन स्तर के साथ किसी भी कंपाइलर को चालक को कॉल करने के लिए कॉल को elide करना चाहिए। लेकिन फिर, यह किसी भी तरह से आपको भरोसा नहीं करना चाहिए। –

0

मुझे लगता है कि यह काम करेगा और संकलक अनुकूलन पर निर्भर नहीं होगा:

data randomize() 
{ 
    // ... 
    data d 
    // ... 
    return std::move(d); 
} 

वापसी मान स्थानीय चर घ के विनाश से पहले का निर्माण किया जाना है।

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