2012-07-06 14 views
6

मैं अभी भी सी ++ सीख रहा हूं, इसलिए कृपया मेरे साथ भालू। मैं बूस्ट फाइल सिस्टम पथ के चारों ओर एक साधारण रैपर लिख रहा हूं - मुझे लौटने वाले अस्थायी तारों के साथ अजीब समस्याएं आ रही हैं।अस्थायी std :: स्ट्रिंग जंक

typedef const char* CString; 
typedef std::string String; 
typedef boost::filesystem::path Path; 

class FileReference { 

    public: 

     FileReference(const char* path) : mPath(path) {}; 

     // returns a path 
     String path() const { 
      return mPath.string(); 
     }; 

     // returns a path a c string 
     CString c_str() const { 
      return mPath.string().c_str(); 
     }; 

    private: 

     Path mPath; 

} 
नीचे थोड़ा परीक्षण कोड के साथ

: यहाँ मेरी साधारण क्लास (इस सटीक नहीं है, लेकिन बहुत करीब) है

FileReference file("c:\\test.txt"); 

OutputDebugString(file.path().c_str()); // returns correctly c:\test.txt 
OutputDebugString(file.c_str());  // returns junk (ie îþîþîþîþîþîþîþîþîþîþî.....) 

मैं बहुत यकीन है कि यह temporaries से निपटने के लिए है, लेकिन मैं यह पता नहीं लगा सकता कि ऐसा क्यों होगा - सबकुछ ठीक से कॉपी नहीं करना चाहिए?

+0

'आउटपुटडिबगस्ट्रिंग()' के लिए स्रोत क्या है? –

+2

अपने स्वयं के 'सीएसटींग'' के 'टाइपेडफ' पर क्रिंग किया गया ... – Blindy

+1

@OtotoAllmendinger - यह एक [विंडोज एपीआई] है (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363362 (v = vs.85) .aspx) फ़ंक्शन। –

उत्तर

4

ऐसा लगता है कि mPath.string() मूल्य के आधार पर एक स्ट्रिंग देता है। फ़ाइल अस्थायी :: c_str() रिटर्न जैसे ही अस्थायी स्ट्रिंग ऑब्जेक्ट को नष्ट कर दिया जाता है, इसलिए इसका c_str() अमान्य हो जाता है। ऐसे मॉडल के साथ, c_str() फ़ंक्शन को स्ट्रिंग के लिए किसी प्रकार का क्लास- या स्थैतिक-स्तरीय चर लागू किए बिना फ़ंक्शन बनाना संभव नहीं है।

पर विचार करें निम्न विकल्पों:

//Returns a string by value (not a pointer!) 
//Don't call it c_str() - that'd be misleading 
String str() const 
{    
    return mPath.string(); 
} 

या

void str(String &s) const 
{    
    s = mPath.string(); 
} 
+0

पहले सुझाव के लिए एक वैध उपयोग 'आउटपुटडिबगस्ट्रिंग (file.str() होगा। c_str()); ' –

8
CString c_str() const { 
     return mPath.string().c_str(); 
    }; 

mPath.string() एक std::string की एक प्रति देता है। वह प्रति अस्थायी रूप से संग्रहीत है जो इस अभिव्यक्ति के अंत में नष्ट हो जाएगी।

.c_str() स्मृति में एक सूचक लौटाता है जो स्ट्रिंग नष्ट होने पर नष्ट हो जाएगा, यानी इस अभिव्यक्ति के अंत में।

आप स्मृति में एक सूचक लौट रहे हैं जो पहले ही नष्ट हो चुका है।

+1

यदि वह एक पॉइंटर चाहता है तो वह m_path.c_str() – PermanentGuest

+0

@PermanentGuest - वापस आ सकता है? मुझे बूस्ट में '.c_str() 'नहीं मिल रहा है। फाइल सिस्टम [दस्तावेज़ीकरण] (http://www.boost.org/doc/libs/1_41_0/libs/filesystem/doc/reference.html#Class-template- basic_path)। –

+0

@ रोब: उन दस्तावेज़ लगभग तीन वर्ष पुराने हैं। [_current_ डॉक्स] (http://www.boost.org/doc/libs/1_50_0/libs/filesystem/doc/reference.html#path-native-format-observers) इसका जिक्र करें। ; -] (यह शायद फाइलसिस्टम v3 में जोड़ा गया था।) – ildjarn

0

भाव

OutputDebugString(file.path().c_str()) 

और

OutputDebugString(file.c_str()) 

कि में समान हैं वे दोनों प्रभावी रूप से एक अस्थायी std::string वस्तु पर c_str() विधि कॉल और है कि कॉल के परिणाम का उपयोग करने का प्रयास। पहला इसे सीधे file.path().c_str() उप-संपीड़न के रूप में कॉल करता है। दूसरा यह अधिक स्पष्ट रूप से करता है: FileReference::c_str() विधि के अंदर।

पहले मामले में अस्थायी std::string ऑब्जेक्ट स्पष्ट रूप से संपूर्ण अभिव्यक्ति के तत्काल हिस्से के रूप में file.path() कॉल द्वारा बनाया गया है। भाषा के नियमों के अनुसार उस अस्थायी वस्तु का जीवनकाल पूरी अभिव्यक्ति के अंत तक फैलता है, यही कारण है कि c_str() कॉल का अस्थायी और परिणाम पूरे समय वैध रहता है।

दूसरे मामले में अस्थायी std::string ऑब्जेक्ट FileReference::c_str() विधि के अंदर बनाया गया है। यह विधि लौटाती है जब उस अस्थायी वस्तु को नष्ट कर दिया जाता है, जिसका अर्थ है कि FileReference::c_str() "मृत" डेटा के लिए एक सूचक देता है। प्रश्न में "जंक" का यही कारण है।

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