2010-05-06 13 views
15

मैं एम्बेडेड सिस्टम के लिए कुछ सी ++ में उपयोगकर्ता स्पेस लिनक्स सॉकेट कार्यक्षमता को लपेट रहा हूं (हाँ, यह संभवतः फिर से पहिया को फिर से शुरू कर रहा है)।सीधे सी ++ std में पढ़ा() का उपयोग करना: वेक्टर

मैं एक वेक्टर का उपयोग करके एक पढ़ना और लिखना कार्यान्वयन देना चाहता हूं।

लेखन करना बहुत आसान है, मैं बस &myvec[0] पास कर सकता हूं और अनावश्यक प्रतिलिपि से बच सकता हूं। मैं एक ऐसा करना चाहता हूं और एक चार बफर में पढ़ने के बजाय सीधे एक वेक्टर में पढ़ना चाहता हूं, फिर इसे सभी नव निर्मित वेक्टर में कॉपी करना।

अब, मुझे पता है कि मैं कितना डेटा पढ़ना चाहता हूं, और मैं उचित रूप से आवंटित कर सकता हूं (vec.reserve())। मैं &myvec[0] में भी पढ़ सकता हूं, हालांकि यह शायद एक बहुत खराब विचार है। जाहिर है यह करने से myvec.size को समझदार कुछ भी वापस करने की अनुमति नहीं है। वहाँ यह है कि ऐसा करने का कोई तरीका है:

  1. पूरी तरह से एक सुरक्षा से yucky महसूस नहीं करता/C++ परिप्रेक्ष्य
  2. डेटा ब्लॉक की दो प्रतियां शामिल नहीं करता है - एक बार गिरी से उपयोगकर्ता अंतरिक्ष के लिए और एक बार से एक सी +12 वेक्टर में सी char * स्टाइल बफर।
+0

क्या एक वेक्टर? –

+0

वर्णों का एक वेक्टर (अच्छी तरह से, बाइट्स)! – Joe

+0

शायद आप बाइट्स के लिए 'uint8_t' या' unsigned char 'का उपयोग करना चाहते हैं। – tzaman

उत्तर

22

reserve() के बजाय resize() का उपयोग करें। यह वेक्टर के आकार को सही ढंग से सेट करेगा - और उसके बाद, &myvec[0] सामान्य रूप से, स्मृति के एक आकस्मिक ब्लॉक को इंगित करने की गारंटी देता है।

संपादित करें: पढ़ने और लिखने दोनों के लिए अंतर्निहित सरणी के सूचक के रूप में &myvec[0] का उपयोग सुरक्षित और सी ++ मानक द्वारा काम करने की गारंटी है।

तो क्यों लोग लगातार पूछते हैं कि क्या एक std :: वेक्टर (या std :: सरणी) के तत्वों समीप जमा हो जाती है: यहाँ क्या हर्ब Sutter has to say है? सबसे संभावित कारण यह है कि वे जानना चाहते हैं कि क्या वे डेटा को साझा करने के लिए आंतरिक रूप से पॉइंटर्स खांसी खा सकते हैं, या तो पढ़ने या लिखने के लिए, अन्य कोड जो सी एरे में सौदे करते हैं। यह एक वैध उपयोग है, और एक मानक में गारंटी के लिए पर्याप्त महत्वपूर्ण है।

+0

वह आड़ू है, और निश्चित रूप से उत्तर 2 का जवाब देता है (परीक्षण और काम भी करता है, धन्यवाद! :-)), लेकिन क्या यह दृष्टिकोण सुरक्षित और साफ है, या कोई अन्य तरीका है? मैं मदद नहीं कर सकता लेकिन महसूस करता हूं कि वेक्टरों के पते को पार करने के लिए संगत स्मृति ब्लॉक को खतरनाक लगता है? – Joe

+0

@ जो: हर्ब सटर के शब्दों में: "क्रिंग नहीं" - यह पूरी तरह से सुरक्षित है। उपरोक्त मेरा संपादन और हर्ब सटर के ब्लॉग एंट्री के लिंक देखें। –

+0

बढ़िया! धन्यवाद :-) जैसा कि कभी भी stackoverflow.com बचाता है! – Joe

1

मान लीजिए कि यह एक पीओडी संरचना है, reserve के बजाय resize पर कॉल करें। यदि आप वास्तव में वेक्टर को भरने से पहले डेटा को शून्य से बाहर नहीं करना चाहते हैं तो आप एक खाली डिफ़ॉल्ट कन्स्ट्रक्टर को परिभाषित कर सकते हैं।

यह कुछ हद तक निम्न स्तर है, लेकिन पीओडी structs के निर्माण के अर्थशास्त्र जानबूझकर अस्पष्ट है। यदि memmove को उनकी प्रतिलिपि बनाने की अनुमति है, तो मुझे नहीं लगता कि सॉकेट-रीड क्यों नहीं होना चाहिए।

संपादित करें: आह, बाइट्स, एक संरचना नहीं। खैर, आप एक ही चाल का उपयोग कर सकते हैं, और एक char और एक डिफ़ॉल्ट कन्स्ट्रक्टर के साथ एक संरचना को परिभाषित कर सकते हैं जो इसे प्रारंभ करने के लिए उपेक्षा करता है ... यदि मैं सही ढंग से अनुमान लगा रहा हूं कि आप परवाह है, और यही कारण है कि आप reserve को resize पर कॉल करना चाहते थे पहले स्थान पर।

1

यदि आप चाहते हैं कि वेक्टर डेटा की मात्रा को प्रतिबिंबित करने के लिए, resize() पर दो बार कॉल करें। पढ़ने से पहले, अपने आप को पढ़ने के लिए जगह देने के लिए। एक बार फिर पढ़ने के बाद, वेक्टर के आकार को बाइट्स की संख्या में वास्तव में पढ़ने के लिए सेट करने के लिए। reserve() कोई अच्छा नहीं है, क्योंकि कॉलिंग रिजर्व आपको क्षमता के लिए आवंटित स्मृति तक पहुंचने की अनुमति नहीं देता है।

पहला resize() वेक्टर के तत्वों को शून्य करेगा, लेकिन यह प्रदर्शन प्रदर्शन ओवरहेड बनाने की संभावना नहीं है। यदि ऐसा होता है तो आप पोटाटोस्वाटर के सुझाव का प्रयास कर सकते हैं, या आप डेटा पढ़ने के आकार को प्रतिबिंबित करने वाले वेक्टर के आकार को छोड़ सकते हैं, और इसके बजाय केवल resize() इसे एक बार फिर से उपयोग कर सकते हैं, फिर इसे फिर से उपयोग करें जैसे आप सी में आवंटित बफर करेंगे

प्रदर्शन-वार, यदि आप उपयोगकर्ता मोड में सॉकेट से पढ़ रहे हैं, तो संभव है कि आप डेटा को जितनी जल्दी हो सके डेटा को आसानी से संभाल सकें। हो सकता है कि आप एक गीगाबिट लैन पर किसी अन्य मशीन से कनेक्ट नहीं हो रहे हैं, या यदि आपकी मशीन अक्सर 100% सीपीयू या 100% मेमोरी बैंडविड्थ चला रही है। अगर आप अंततः read कॉल पर ब्लॉक करने जा रहे हैं तो अतिरिक्त प्रतिलिपि या यादृच्छिकता का कोई बड़ा सौदा नहीं है।

आप की तरह, मैं उपयोगकर्ता-स्थान में अतिरिक्त प्रतिलिपि से बचना चाहता हूं, लेकिन प्रदर्शन कारणों से नहीं, सिर्फ इसलिए कि अगर मैं ऐसा नहीं करता, तो मुझे इसके लिए कोड लिखना नहीं है ..

+0

आम तौर पर मुझे वास्तव में अतिरिक्त प्रति की परवाह नहीं है, लेकिन मैं कम संसाधनों के साथ एक वास्तविक समय प्रणाली पर हूं। पूरी पढ़ी/लिखने की प्रक्रिया गैर-अवरुद्ध है। बेशक, यह स्पष्ट रूप से एक वास्तविक समय प्रणाली बनाम स्थिर स्मृति आवंटन आदि में एसटीएल कंटेनरों के बारे में प्रश्नों की ओर जाता है .... – Joe

1

मैं केवल एक संक्षिप्त स्पष्टीकरण जोड़ूंगा, क्योंकि उत्तर पहले ही दिया गया था। मौजूदा आकार से अधिक तर्क के साथ आकार बदलें() संग्रह और डिफ़ॉल्ट में तत्व जोड़ देगा - उन्हें प्रारंभ करें। आप

std::vector<unsigned char> v; 

बनाने और उसके बाद का आकार बदलने के

v.resize(someSize); 

सभी अहस्ताक्षरित वर्ण को 0 पर प्रारंभ हो जाएगी तो Btw आप एक निर्माता के साथ भी ऐसा कर सकते हैं

std::vector<unsigned char> v(someSize); 

तो सैद्धांतिक रूप से यह हो सकता है एक कच्चे सरणी की तुलना में थोड़ा धीमा, लेकिन यदि विकल्प सरणी की प्रतिलिपि बनाना है, तो यह बेहतर है।

रिजर्व केवल स्मृति तैयार करता है, ताकि संग्रह में नए तत्व जोड़े जाने पर कोई पुनर्वितरण आवश्यक न हो, लेकिन आप उस स्मृति तक नहीं पहुंच सकते हैं।

आपको अपने वेक्टर को लिखे गए तत्व की संख्या के बारे में जानकारी प्राप्त करनी है। वेक्टर इसके बारे में कुछ नहीं जान पाएंगे।

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