कैसे शुरू करें एसटीडी :: सी-स्टाइल ऐरे से वेक्टर?


174

std::vectorC- शैली सरणी से आरंभ करने का सबसे सस्ता तरीका क्या है ?

उदाहरण: निम्न वर्ग में, मेरे पास एक है vector, लेकिन बाहरी प्रतिबंधों के कारण, डेटा को C- शैली सरणी के रूप में पारित किया जाएगा:

class Foo {
  std::vector<double> w_;
public:
  void set_data(double* w, int len){
   // how to cheaply initialize the std::vector?
}

जाहिर है, मैं कॉल कर सकता हूं w_.resize()और फिर तत्वों पर लूप, या कॉल कर सकता हूं std::copy()। क्या कोई बेहतर तरीके हैं?


11
समस्या की जड़ यह है कि वेक्टर के लिए यह जानने का कोई तरीका नहीं है कि क्या आपके सी-स्टाइल ऐरे को बनाने के लिए उसी एलोकेटर का उपयोग किया गया था। जैसे कि वेक्टर को अपने आवंटनकर्ता का उपयोग करके मेमोरी आवंटित करनी चाहिए। अन्यथा यह केवल अंतर्निहित सरणी को स्वैप कर सकता है और इसे आपके सरणी से बदल सकता है।
Void

जवाबों:


233

यह मत भूलो कि आप बिंदुओं को पुनरावृत्तियों के रूप में मान सकते हैं:

w_.assign(w, w + len);

3
यह कार्यान्वयन के मुद्दे की एक गुणवत्ता है। चूंकि पुनरावृत्तियों में ऐसे टैग होते हैं जो उनकी श्रेणियों को निर्दिष्ट करते हैं, इसलिए उनका assignउपयोग करने के लिए उनका उपयोग करने के लिए निश्चित रूप से एक नि: शुल्क है; कम से कम VC ++ में, यह वास्तव में ऐसा ही करता है।
पावेल मिनेव

38
त्वरित समाधान std :: वेक्टर <double> w_ (w, w + len) हो सकता है;
जाम

1
यह 'w_' के लिए नए बनाए गए स्टोरेज के तत्वों को कॉपी करता है; 'w_.data' 'w' की ओर इशारा नहीं करेगा। आपको अभी भी 'w' से निपटना होगा। कोई स्वामित्व हस्तांतरण नहीं है
Indy9000

1
यदि यह अंत में एक तत्व है, तो यह ठीक होना चाहिए (जैसा v.end()कि एक पुनरावृत्त एक समान मामले में वेक्टर के साथ एक अतीत को इंगित करता है)। यदि आप एक जोर मिलता है, तो कहीं और से कुछ है।
पावेल मिनाएव

1
बस जल्दी से, यह वेक्टर मेमोरी से निपटेगा जब वेक्टर गुंजाइश से बाहर जाता है?
एड्रियन कोच

41

आप इनिशियलाइज़ शब्द का उपयोग करते हैं इसलिए यह अस्पष्ट है कि यह एक बार असाइनमेंट है या कई बार हो सकता है।

यदि आपको बस एक बार आरंभीकरण की आवश्यकता है, तो आप इसे कंस्ट्रक्टर में रख सकते हैं और दो इटेरेटर वेक्टर कंस्ट्रक्टर का उपयोग कर सकते हैं:

Foo::Foo(double* w, int len) : w_(w, w + len) { }

अन्यथा पहले दिए गए सुझाव के अनुसार असाइन का उपयोग करें:

void set_data(double* w, int len)
{
    w_.assign(w, w + len);
}

1
मेरे मामले में, असाइनमेंट बार-बार होगा।
फ्रैंक

12

आप स्वचालित रूप से सरणी के आकार को 'सीख' सकते हैं:

template<typename T, size_t N>
void set_data(const T (&w)[N]){
    w_.assign(w, w+N);
}

उम्मीद है, आप ऊपर के रूप में set_data के लिए इंटरफ़ेस बदल सकते हैं। यह अभी भी अपने पहले तर्क के रूप में एक सी-शैली सरणी को स्वीकार करता है। यह सिर्फ संदर्भ से लेना होता है।


यह काम किस प्रकार करता है

[अद्यतन: आकार सीखने पर अधिक व्यापक चर्चा के लिए यहां देखें ]

यहाँ एक अधिक सामान्य समाधान है:

template<typename T, size_t N>
void copy_from_array(vector<T> &target_vector, const T (&source_array)[N]) {
    target_vector.assign(source_array, source_array+N);
}

यह काम करता है क्योंकि सरणी को संदर्भ-दर-सरणी के रूप में पारित किया जा रहा है। C / C ++ में, आप एक एरे को फंक्शन के रूप में पास नहीं कर सकते हैं, इसके बजाय यह एक पॉइंटर को क्षय कर देगा और आप आकार खो देंगे। लेकिन C ++ में, आप सरणी के लिए एक संदर्भ पारित कर सकते हैं।

एक सरणी को संदर्भ द्वारा पास करने से प्रकारों का सटीक मिलान करने की आवश्यकता होती है। एक सरणी का आकार इसके प्रकार का हिस्सा है। इसका मतलब है कि हम हमारे लिए आकार जानने के लिए टेम्पलेट पैरामीटर एन का उपयोग कर सकते हैं।

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

template<typename T, size_t N>
vector<T> convert_array_to_vector(const T (&source_array)[N]) {
    return vector<T>(source_array, source_array+N);
}

1
अंतिम नमूने में, return { begin(source_array), end(source_array) };यह भी संभव है
MM

12

खैर, पावेल करीब था, लेकिन एसी शैली सरणी से एक अनुक्रमिक कंटेनर को इनिशियलाइज़ करने के लिए और भी सरल और सुरुचिपूर्ण समाधान है।

आपके मामले में:

w_ (array, std::end(array))
  • सरणी हमें सरणी की शुरुआत के लिए एक संकेतक मिलेगा (यह नाम नहीं पकड़ता है),
  • std :: end (एरे) हमें एरे के अंत में एक पुनरावृत्तिकर्ता मिलेगा।

1
C ++ के संस्करण / संस्करण में क्या शामिल है?
व्लाद

1
यह std के निर्माता में से एक है: वेक्टर कम से कम c ++ 98 से आगे .... इसे 'रेंज कंस्ट्रक्टर' कहा जाता है। cplusplus.com/reference/vector/vector/vector इसे आज़माएं।
मुगुरेल

1
अधिक स्वतंत्र संस्करण है: w_ (std :: start (array), std :: end (array)); (भविष्य में आप सी ++ कंटेनर के लिए सी सरणी को बदल सकते हैं)।
एंड्रयू रोमानोव

13
ध्यान रहे, यह केवल तभी काम करता है जब आपके पास एक वास्तविक array(जिसका अर्थ है आमतौर पर आप एक वैश्विक या स्थानीय (वर्तमान फ़ंक्शन में घोषित) सरणी से कॉपी कर रहे हैं)। ओपी के मामले में, वह एक पॉइंटर और एक लंबाई प्राप्त कर रहा है, और क्योंकि यह लंबाई पर टेम्पलेटेड नहीं है, इसलिए वे पॉइंटर को एक आकार सरणी या कुछ भी करने के लिए नहीं बदल सकते हैं, इसलिए std::endकाम नहीं करेगा।
शैडो रेंजर

2
vectorअधिक भार नहीं है operator(), इसलिए यह संकलन नहीं करेगा। std::endएक पॉइंटर पर कॉल किया जा रहा है या तो कोई उपयोग नहीं है (प्रश्न एक पॉइंटर को पॉइंटर और एक अलग लंबाई चर से असाइन करने के लिए कहता है)। यह आपके सुझाव को बेहतर बनाने के लिए कि आप क्या सुझाव देने की कोशिश कर रहे हैं, के बारे में अधिक जानकारी दिखाने के लिए
MM

2

त्वरित सामान्य उत्तर:

std::vector<double> vec(carray,carray+carray_size); 

या विशिष्ट प्रश्न:

std::vector<double> w_(w,w+len); 

ऊपर आधारित : यह मत भूलिए कि आप पॉइंटर्स को पुनरावृत्तियों के रूप में मान सकते हैं


0

std::vector<double>::assignजाने का रास्ता है, क्योंकि यह थोड़ा कोड है । लेकिन यह कैसे काम करता है, वास्तव में? यह आकार नहीं है और फिर कॉपी? एसटीएल के एमएस कार्यान्वयन में मैं इसका उपयोग कर रहा हूं, ठीक ऐसा ही है।

मुझे डर है कि आपके प्रारंभ को लागू करने (पुनः) को लागू करने का कोई तेज़ तरीका नहीं हैstd::vector


क्या होगा यदि डेटा वेक्टर और एक सरणी के बीच साझा किया जाए? क्या हमें इस मामले में कुछ भी कॉपी करने की आवश्यकता है?
व्लाद

यह एक जवाब है या एक सवाल है? क्या यह पहले से मौजूद जवाबों को लाता है?
जीन फ़्राँस्वा Fabre

@ जीन-फ्रांस्वा फाबरे और आपकी टिप्पणी क्या लाती है? ;) सच है, यह एक खराब जवाब है, जो सदियों पहले दिया गया था।
जानुस लेनार
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.