2008-08-28 17 views
34

यह एक डिजाइन सवाल नहीं है, वास्तव में, हालांकि यह ऐसा प्रतीत हो सकता है। (ठीक है, ठीक है, यह एक डिजाइन सवाल है)। मैं क्या सोच रहा हूं कि क्यों सी ++ std::fstream कक्षाएं अपने निर्माता या खुली विधियों में std::string नहीं लेती हैं। हर कोई कोड उदाहरण तो प्यार करता है:std :: fstream कक्षाएं std :: string क्यों नहीं लेती हैं?

#include <iostream> 
#include <fstream> 
#include <string> 

int main() 
{ 
    std::string filename = "testfile";  
    std::ifstream fin; 

    fin.open(filename.c_str()); // Works just fine. 
    fin.close(); 

    //fin.open(filename); // Error: no such method. 
    //fin.close(); 
} 

यह मैं हर समय हो जाता है जब फाइलों के साथ काम। निश्चित रूप से सी ++ लाइब्रेरी std::string का उपयोग कहीं भी करेगी?

उत्तर

26

std::string वर्ग पर एक सी स्ट्रिंग सी ++ 03 std::fstream वर्ग कम निर्भरता लेने से। सी ++ 11 में, हालांकि, std::fstream वर्ग अपने कन्स्ट्रक्टर पैरामीटर के लिए std::string पास करने की अनुमति देता है।

अब, आप सोच रहे होंगे क्यों वहाँ एक सी स्ट्रिंग के लिए एक std:string से एक पारदर्शी रूपांतरण है, तो एक वर्ग को उम्मीद है कि एक सी स्ट्रिंग अभी भी सिर्फ एक वर्ग को उम्मीद है कि एक std::string एक सी ले जा सकते हैं की तरह एक std::string ले सकता है नहीं है स्ट्रिंग।

कारण यह है कि इससे एक रूपांतरण चक्र होगा, जो बदले में समस्याएं पैदा कर सकता है। उदाहरण के लिए, मान लीजिए std::string एक सी स्ट्रिंग में परिवर्तनीय होगा ताकि आप एस के साथ std::string एस का उपयोग कर सकें। मान लीजिए कि सी स्ट्रिंग परिवर्तनीय है std::string एस वर्तमान मानक में राज्य है।

void f(std::string str1, std::string str2); 
void f(char* cstr1, char* cstr2); 

void g() 
{ 
    char* cstr = "abc"; 
    std::string str = "def"; 
    f(cstr, str); // ERROR: ambiguous 
} 

क्योंकि आप एक std::string और एक सी स्ट्रिंग f() करने के लिए कॉल दो f() विकल्प में से किसी को हल कर सकता है, और इस तरह से अस्पष्ट है के बीच किसी भी तरह से परिवर्तित कर सकते हैं: अब, निम्नलिखित पर विचार करें। समाधान एक रूपांतरण दिशा स्पष्ट करके रूपांतरण चक्र को तोड़ना है, एसटीएल ने c_str() के साथ क्या करना चुना है।

+1

नमूना अधिभार संकल्प नियमों के साथ किसी अस्पष्टता का कारण नहीं बनना चाहिए। 'एफ (char *, std :: string)' एक [सटीक मिलान] है (http://www.lcdf.org/c++/clause13.html#s13.3.3.1.1) जबकि अन्य को रूपांतरण की आवश्यकता होगी, इसलिए सबसे अच्छा व्यवहार्य समारोह होगा।यदि आपने पहले 'f' को हटा दिया है, तो, "(char * &, std :: string &) -> (char *, std :: string) -> (char *, char *)" एक [बेहतर रूपांतरण अनुक्रम है) ] (http://www.lcdf.org/c++/clause13.html#s13.3.3) की तुलना में "(चार * &, std :: स्ट्रिंग और) -> (चार *, std :: स्ट्रिंग) -> (एसटीडी: : स्ट्रिंग, चार *) ", दूसरा 'एफ' सबसे अच्छा व्यवहार्य कार्य होगा। क्या मैं कुछ भूल रहा हूँ? – outis

+0

जैसा कि मैं हूं, ठीक है। – wilhelmtell

+2

इस माइक्रो अनुकूलन वास्तव में मूर्खतापूर्ण, के रूप में (1) तार कसकर भाषा के किसी भी निर्माण के लिए युग्मित कर रहे हैं, विशेष रूप से तार के साथ (यह कह के समान है, मैं शॉर्ट्स पर निर्भर 'नहीं करना चाहती GMP'), और (2) 'चार *', बुराई है आप अगर वे की जरूरत नहीं है इसका इस्तेमाल करने के लिए उपयोगकर्ताओं प्रोत्साहित नहीं करना चाहिए, और संकलन समय में मिलीसेकंड में अच्छी तरह से इसके लायक है, अंत में (3) वे परिभाषित कर सकता था '' और उपयोग इसके आधार पर स्ट्रिंग, इसलिए मैं दावा करता हूं कि इस मामले के लिए decoupling निर्भरता वैध कारण नहीं है। –

0

वहाँ एसटीएल में किसी भी वर्ग है कि एक स्ट्रिंग लेता है ... लगता है कि मैं न तो (सके मेरी त्वरित खोज में किसी भी लगता है)। तो शायद यह कुछ डिज़ाइन निर्णय है, कि एसटीएल में कोई भी वर्ग किसी भी अन्य एसटीएल वर्ग (जो कार्यक्षमता के लिए सीधे आवश्यक नहीं है) पर निर्भर होना चाहिए।

14

कई स्थानों पर जहां सी ++ मानक समिति वास्तव में मानक पुस्तकालय में सुविधाओं के बीच बातचीत का अनुकूलन नहीं किया हैं।

std::string और पुस्तकालय में इसके उपयोग इन में से एक है।

एक अन्य उदाहरण std::swap है। कई कंटेनरों में एक स्वैप सदस्य फ़ंक्शन होता है, लेकिन std :: स्वैप की कोई अधिभार नहीं की जाती है। यह std::sort के लिए जाता है।

मुझे आशा है कि ये सभी छोटी चीजें आने वाले मानक में तय की जाएंगी।

0

मुझे विश्वास है कि इस पर विचार किया गया है और निर्भरता से बचने के लिए किया गया था; यानी #fstream > को < स्ट्रिंग > को शामिल करने के लिए मजबूर नहीं होना चाहिए।

ईमानदार होने के लिए, यह काफी अप्रिय समस्या की तरह लगता है। एक बेहतर सवाल होगा, std :: स्ट्रिंग का इंटरफ़ेस इतना बड़ा क्यों है?

2

ऐसा नहीं है कि सच है अप्रासंगिक है। Std :: स्ट्रिंग का इंटरफ़ेस बड़ा होने का क्या मतलब है? इसका मतलब क्या है, इस संदर्भ में - बहुत सी विधि कॉल करती हैं? मैं मुखर नहीं हूं, मैं वास्तव में रूचि रखता हूं।

यह तुलना में यह वास्तव में जरूरत है, और नहीं बल्कि iterators से अभिन्न ऑफसेट का उपयोग कर के अपने व्यवहार में थोड़ा iffy है (के रूप में यह पुस्तकालय काम करता है के बाकी रास्ते के विपरीत है) और अधिक तरीकों है।

असली समस्या मुझे लगता है कि सी ++ लाइब्रेरी में तीन हिस्से हैं; इसमें पुरानी सी लाइब्रेरी है, इसमें एसटीएल है, और इसमें स्ट्रिंग्स-एंड-आईस्ट्रीम हैं। यद्यपि विभिन्न हिस्सों को पुल करने के लिए कुछ प्रयास किए गए थे (उदाहरण के लिए सी लाइब्रेरी में ओवरलोड का जोड़ा, क्योंकि सी ++ ओवरलोडिंग का समर्थन करता है; इटरेटर को मूल_स्ट्रिंग के अलावा; आईस्ट्रीम इटरेटर एडाप्टर के अतिरिक्त), जब आप बहुत असंगतताएं हैं विवरण देखें।

उदाहरण के लिए, basic_string तरीकों कि मानक एल्गोरिदम के अनावश्यक डुप्लिकेट हैं शामिल हैं; विभिन्न खोज विधियों, शायद सुरक्षित रूप से हटाया जा सकता है। एक और उदाहरण: स्थानीय लोग इटरेटर के बजाय कच्चे पॉइंटर्स का उपयोग करते हैं।

3

@ बर्नार्ड:
मोनोलिथ्स "अनस्ट्रांग"। "सभी के लिए सभी, और सभी के लिए एक" मस्किटियर के लिए काम कर सकता है, लेकिन यह कक्षा डिजाइनरों के लिए लगभग भी काम नहीं करता है। यहां एक उदाहरण दिया गया है जो पूरी तरह से अनुकरणीय नहीं है, और यह दिखाता है कि जब डिज़ाइन ओवरडिज़ाइन में बदल जाता है तो आप कितनी बुरी तरह गलत हो सकते हैं। उदाहरण के लिए, दुर्भाग्य से, ... आप के पास एक मानक पुस्तकालय से लिया जाता है ~ http://www.gotw.ca/gotw/084.htm

11

शायद यह एक सांत्वना है: सब fstream का एक खुला मिल गया है (स्ट्रिंग स्थिरांक &, ...) अगले खुला (चार स्थिरांक को *, ...) सी ++ 0x मानक के कामकाजी मसौदे में। (basic_ifstream घोषणा के लिए जैसे 27.8.1.6 देखें)

इसलिए, जब अंतिम रूप दे दिया है और कार्यान्वित हो जाता है, तो यह आपको अब और नहीं मिलेगा :)

9

धारा आईओ पुस्तकालय से पहले मानक सी ++ पुस्तकालय में जोड़ा गया है एसटीएल पिछड़े संगतता को तोड़ने के लिए, आईटी लाइब्रेरी को संशोधित करने से बचने का निर्णय लिया गया है जब एसटीएल जोड़ा गया था, भले ही इसका मतलब आपके द्वारा उठाए गए कुछ मुद्दों जैसा था।

1

सी ++ उन राक्षसों की तुलना में छोटी मशीनों पर बड़ा हुआ जो हम आज के लिए कोड लिखते हैं। वापस जब iostream नया था कई डेवलपर्स वास्तव में कोड आकार के बारे में परवाह करते थे (उन्हें अपने पूरे कार्यक्रम और डेटा को कई सौ केबी में फिट करना था)। इसलिए, कई "बड़ी" सी ++ स्ट्रिंग लाइब्रेरी में नहीं खींचना चाहते थे। कई लोगों ने उसी कारण, कोड आकार के लिए iostream लाइब्रेरी का भी उपयोग नहीं किया।

हमारे पास आज की तरह फेंकने के लिए हजारों मेगाबाइट रैम नहीं थे। हमारे पास आमतौर पर फ़ंक्शन स्तर लिंकिंग नहीं होता था, इसलिए हम लाइब्रेरी के डेवलपर की दया पर बहुत अलग ऑब्जेक्ट फ़ाइलों का उपयोग करने के लिए थे या फिर अनचाहे कोड में खींचते थे। इन सभी एफयूडी ने डेवलपर्स को std :: स्ट्रिंग से दूर चलाया।

वापस तब मैंने std :: स्ट्रिंग से परहेज किया। "बहुत फूला हुआ", "जिसे मॉलोक भी अक्सर कहा जाता है", आदि तारों के लिए स्टैक-आधारित बफर का उपयोग करके मूर्खतापूर्वक, फिर यह सुनिश्चित करने के लिए सभी प्रकार के थकाऊ कोड जोड़ते हैं कि यह अधिक नहीं हो जाता है।

0

आजकल आप इस समस्या को बहुत आसानी से हल कर सकते हैं: -std=c++11 को अपने CFLAGS पर जोड़ें।