"स्पैन" क्या है और मुझे कब उपयोग करना चाहिए?


237

हाल ही में मैंने span<T>अपने कोड में उपयोग करने के लिए सुझाव दिए हैं , या साइट पर यहाँ कुछ उत्तर देखे हैं जो spanकि किसी प्रकार के कंटेनर का उपयोग करते हैं। लेकिन - मुझे C ++ 17 मानक पुस्तकालय में ऐसा कुछ नहीं मिला।

तो यह रहस्यमय क्या है span<T>, और क्यों (या कब) यह गैर-मानक होने पर इसका उपयोग करना एक अच्छा विचार है?


std::span2017 में प्रस्तावित किया गया था। यह C ++ 17 या C ++ 20 पर लागू होता है। P0122R5, स्पैन भी देखें : वस्तुओं के अनुक्रम के लिए सीमा-सुरक्षित दृश्य । क्या आप वास्तव में उस भाषा को लक्षित करना चाहते हैं? यह कंपाइलर पकड़ने से पहले का साल होगा।
jww

6
@jww: स्पैन सी ++ 11 के साथ काफी प्रयोग करने योग्य हैं ... gsl::spanइसके बजाय std::span। नीचे मेरा जवाब भी देखिए।
ईनपोकलम

Cppreference.com पर भी प्रलेखित: en.cppreference.com/w/cpp/container/span
कीथ थॉम्पसन

1
@KeithThompson: 2017 में ऐसा नहीं था ...
einpoklum

@jww सभी कंपाइलर्स std :: span <> अब C ++ 20 मोड में सपोर्ट करते हैं। और स्पैन कई 3 पार्टी के लिबास से उपलब्ध है। आप सही थे - यह साल था: सटीक होने के लिए 2 साल।
कंटैंगो

जवाबों:


272

यह क्या है?

span<T>है:

  • Tस्मृति में कहीं प्रकार के मूल्यों के एक सन्निहित अनुक्रम का एक बहुत हल्का अमूर्त ।
  • मूल रूप struct { T * ptr; std::size_t length; }से सुविधा विधियों के एक समूह के साथ।
  • एक गैर-स्वामित्व वाला प्रकार (अर्थात "मान प्रकार" के बजाय "संदर्भ-प्रकार "): यह कभी भी किसी चीज़ का आवंटन नहीं करता है और न ही करता है और स्मार्ट पॉइंटर्स को जीवित नहीं रखता है।

यह पहले एक के रूप में जाना जाता था array_viewऔर पहले भी के रूप में जाना जाता था array_ref

मुझे इसका उपयोग कब करना चाहिए?

सबसे पहले, जब इसका उपयोग नहीं करना है:

  • कोड में यह प्रयोग न करें कि सिर्फ शुरुआत और अंत iterators, के किसी भी जोड़े ले सकता है की तरह std::sort, std::find_if, std::copyऔर उन सुपर सामान्य टेम्प्लेट की गई सभी कार्यों के।
  • यदि आपके पास एक मानक पुस्तकालय कंटेनर (या बूस्ट कंटेनर आदि) है, जो आपको पता है कि आपके कोड के लिए सही फिट है तो इसका उपयोग न करें। यह उनमें से किसी को भी दबाने का इरादा नहीं है।

अब वास्तव में इसका इस्तेमाल कब करना है:

फ्री-स्टैंडिंग (क्रमशः ) के बजाय span<T>(क्रमशः span<const T>) का उपयोग करें , जिसके लिए आपके पास लंबाई मान है। इसलिए, जैसे कार्यों को बदलें:T*const T*

  void read_into(int* buffer, size_t buffer_size);

साथ में:

  void read_into(span<int> buffer);

मुझे क्यों इसका उपयोग करना चाहिए? यह अच्छी बात क्यों है?

ओह, स्पैन कमाल हैं! एक का उपयोग कर span...

  • इसका मतलब है कि आप उस पॉइंटर + लेंथ / स्टार्ट + एंड पॉइंटर कॉम्बिनेशन के साथ काम कर सकते हैं, जैसे आप एक फैंसी, पिंपड-आउट स्टैंडर्ड लाइब्रेरी कंटेनर, जैसे:

    • for (auto& x : my_span) { /* do stuff */ }
    • std::find_if(my_span.begin(), my_span.end(), some_predicate);

    ... लेकिन पूरी तरह से ओवरहेड अधिकांश कंटेनर कक्षाओं में से कोई भी नहीं है।

  • कंपाइलर कभी-कभी आपके लिए अधिक काम करता है। उदाहरण के लिए, यह:

    int buffer[BUFFER_SIZE];
    read_into(buffer, BUFFER_SIZE);

    यह बन जाता है:

    int buffer[BUFFER_SIZE];
    read_into(buffer);

    ... जो आप करना चाहते हैं वह करेंगे। दिशानिर्देश पी 5 भी देखें ।

  • const vector<T>&जब आप अपने डेटा को स्मृति में सन्निहित होने की अपेक्षा करते हैं, तो फ़ंक्शन को पास करने का उचित विकल्प है । कोई और अधिक उच्च और शक्तिशाली सी ++ गुरु द्वारा डांटा जा रहा है!

  • स्थिर विश्लेषण की सुविधा देता है, इसलिए संकलक आपको मूर्खतापूर्ण कीड़े पकड़ने में मदद करने में सक्षम हो सकता है।
  • रनटाइम सीमा-जाँच के लिए डिबग-संकलन इंस्ट्रूमेंटेशन के लिए अनुमति देता है (यानी spanतरीकों में कुछ सीमा-जाँच कोड होगा #ifndef NDEBUG... #endif)
  • इंगित करता है कि आपका कोड (स्पैन का उपयोग कर रहा है) इंगित की गई मेमोरी का मालिक नहीं है।

spanS का उपयोग करने के लिए और भी अधिक प्रेरणा है , जिसे आप C ++ कोर दिशानिर्देशों में पा सकते हैं - लेकिन आप बहाव को पकड़ते हैं।

यह मानक पुस्तकालय (C ++ 17 के अनुसार) में क्यों नहीं है?

यह मानक पुस्तकालय में है - लेकिन केवल C ++ 20 के रूप में। इसका कारण यह है कि यह अभी भी अपने वर्तमान रूप में बहुत नया है, C ++ कोर दिशानिर्देश परियोजना के संयोजन में कल्पना की गई है , जो केवल 2015 से ही आकार ले रही है (हालांकि टिप्पणीकार बताते हैं, इसका पहले का इतिहास है।)

अगर मैं अभी तक मानक पुस्तकालय में नहीं हूं तो मैं इसका उपयोग कैसे करूं?

यह कोर दिशानिर्देशों के समर्थन पुस्तकालय (जीएसएल) का हिस्सा है। कार्यान्वयन:

  • Microsoft / नील मैकिंटोश के GSL में एक स्टैंडअलोन कार्यान्वयन शामिल है:gsl/span
  • जीएसएल-लाइट पूरे जीएसएल का एकल-हेडर कार्यान्वयन है (यह इतना बड़ा नहीं है, चिंता न करें) सहित span<T>

जीएसएल कार्यान्वयन आम तौर पर एक प्लेटफ़ॉर्म मान लेता है जो C ++ 14 समर्थन [ 14 ] को लागू करता है । ये वैकल्पिक सिंगल-हेडर कार्यान्वयन जीएसएल सुविधाओं पर निर्भर नहीं करते हैं:

  • martinmoene/span-lite C ++ 98 या बाद के संस्करण की आवश्यकता है
  • tcbrindle/span C ++ 11 या बाद के संस्करण की आवश्यकता है

ध्यान दें कि इन अलग-अलग अवधि के कार्यान्वयन में कुछ अंतर हैं कि वे किन तरीकों / समर्थन कार्यों के साथ आते हैं; और वे मानक लायब्रेरी सी ++ 20 में जाने वाले संस्करण से कुछ भिन्न हो सकते हैं।


आगे पढ़ना: आप C ++ 17, P0122R7 से पहले अंतिम आधिकारिक प्रस्ताव में सभी विवरण और डिजाइन विचार पा सकते हैं: अवधि: नील मैकिन्टोश और स्टीफन जे लावेज द्वारा वस्तुओं के अनुक्रम के लिए सीमा-सुरक्षित विचार । हालांकि यह थोड़ा लंबा है। इसके अलावा, C ++ 20 में, स्पैन तुलना शब्दार्थ ( टोनी वैन एर्ड द्वारा इस लघु पेपर के बाद) बदल गया ।


2
यह सामान्य श्रेणी को मानकीकृत करने के लिए और अधिक समझ में आता है (पुनरावृति + प्रहरी और पुनरावृत्ति + लंबाई, शायद पुनरावृत्त + प्रहरी + लंबाई) का समर्थन करना और एक साधारण टाइपफ़ीड बनाना। क्योंकि, आप जानते हैं, यह अधिक सामान्य है।
डेडुप्लिकेटर

3
@ डेडप्लिकेटर: रंग सी + + पर आ रहे हैं, लेकिन वर्तमान प्रस्ताव (एरिक नीब्लर द्वारा) को कॉन्सेप्ट के लिए समर्थन की आवश्यकता है। तो C ++ 20 से पहले नहीं।
ईनपोकलुम

8
@ HriPhạmLê: एरर्स तुरंत संकेत में क्षय नहीं करते हैं। करने की कोशिश करो std::cout << sizeof(buffer) << '\n'और आप देखेंगे कि आपको 100 साइज़ोफ़ (int) मिल रहे हैं।
einpoklum

4
@ जिम std::arrayएक कंटेनर है, यह मूल्यों का मालिक है। spanगैर-मालिक है
Caleth

3
@ जिम: std::arrayपूरी तरह से अलग जानवर है। इसकी लंबाई संकलन-समय पर तय की गई है और यह एक संदर्भ-प्रकार के बजाय एक मूल्य-प्रकार है, जैसा कि कैलथ ने समझाया है।
einpoklum 14

1

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

  1. कैसे है a spanC सरणी से भिन्न है? क्यों नहीं बस उन में से एक का उपयोग करें? ऐसा लगता है कि यह आकार के साथ ही उनमें से एक के रूप में अच्छी तरह से जाना जाता है ...
  2. रुको, यह एक तरह लग रहा है std::array, कैसे इससे spanअलग है?
  3. ओह, यह मुझे याद दिलाता है, std::vectorएक std::arrayबहुत पसंद नहीं है?
  4. मैं बहुत उलझन में हूँ। :( क्या है span?

तो, यहाँ उस पर कुछ अतिरिक्त स्पष्टता है:

मेरे एंकर के प्रत्यक्ष उद्धरण - मेरे नए शब्दों में :

यह क्या है?

span<T>है:

  • Tस्मृति में कहीं प्रकार के मूल्यों के एक सन्निहित अनुक्रम का एक बहुत हल्का अमूर्त ।
  • मूल रूप से सुविधा विधियों के एक समूह के साथ एक एकल संरचना { T * ptr; std::size_t length; }(सूचना इस से अलग है std::array<>क्योंकि एक spanतरीकों एक्सेसर सुविधा, के लिए तुलनीय सक्षम बनाता है std::arrayएक के माध्यम से, टाइप करने के लिए सूचकT और प्रकार की लंबाई (तत्वों की संख्या) T, जबकि std::arrayएक वास्तविक कंटेनर जो एक या अधिक रखती है मानों प्रकार के T।)
  • एक गैर-स्वामित्व वाला प्रकार (अर्थात "मान प्रकार" के बजाय "संदर्भ-प्रकार "): यह कभी भी किसी चीज़ का आवंटन नहीं करता है और न ही करता है और स्मार्ट पॉइंटर्स को जीवित नहीं रखता है।

यह पहले एक के रूप में जाना जाता था array_viewऔर पहले भी के रूप में जाना जाता था array_ref

वे बोल्ड पार्ट्स किसी की समझ के लिए महत्वपूर्ण हैं, इसलिए उन्हें याद न करें या उन्हें गलत न समझें! A spanसंरचना का C-सरणी नहीं है, न ही यह C-array प्रकार की संरचना है और साथ ही सरणी की Tलंबाई भी है (यह अनिवार्य रूप से std::array कंटेनर क्या होगा ), NOR यह बिंदुओं की संरचना का सी-सरणी है टाइप करने के Tलिए लंबाई, लेकिन इसके बजाय यह एक एकल संरचना है जिसमें टाइप करने के लिएT एक एकल पॉइंटर है , और लंबाई , जो सन्निहित मेमोरी ब्लॉक में तत्वों (प्रकार T)Tइस तरह, एक ही ओवरहेड जो आपने एक का उपयोग करके जोड़ा है की संख्या है जो पॉइंटर को टाइप करने के लिए इंगित करता है! spanपॉइंटर और लंबाई को स्टोर करने के लिए चर हैं, और आपके द्वारा उपयोग किए जाने वाले किसी भी सुविधा एक्सेसरी फ़ंक्शनspan प्रदान करता है।

यह UNLIKE है std::array<>क्योंकि std::array<>वास्तव में पूरे सन्निहित ब्लॉक के लिए स्मृति आवंटित करता है, और यह UNLIKE है std::vector<>क्योंकि std::vectorमूल रूप से एक std::arrayऐसा है जो गतिशील रूप से बढ़ता है (आमतौर पर आकार में दोगुना) यह हर बार भरता है और आप इसमें कुछ और जोड़ने की कोशिश करते हैं। । एक std::arrayआकार में तय हो गई है, और एक spanभी ब्लॉक यह बताते हैं के लिए, यह सिर्फ स्मृति के ब्लॉक करने के लिए अंक, जानता है कि कब तक स्मृति के ब्लॉक है, की स्मृति का प्रबंधन नहीं है जानता है कि क्या डेटा प्रकार एक सी सरणी में है मेमोरी में, और उस सन्निहित मेमोरी में तत्वों के साथ काम करने के लिए सुविधा एक्सेसर फ़ंक्शन प्रदान करता है

यह C ++ मानक का हिस्सा है:

std::spanC ++ 20 के रूप में C ++ मानक का हिस्सा है। आप इसके प्रलेखन को यहाँ पढ़ सकते हैं: https://en.cppreference.com/w/cpp/container/span । यह देखने के लिए कि Google का absl::Span<T>(array, length)C ++ 11 या आज के बाद का उपयोग कैसे करें , नीचे देखें।

सारांश विवरण और मुख्य संदर्भ:

  1. std::span<T, Extent>( Extent= "अनुक्रम में तत्वों की संख्या, या std::dynamic_extentगतिशील यदि" एक अवधि सिर्फ। के अंक स्मृति और उपयोग करने के लिए इसे आसान बना देता है, लेकिन यह प्रबंधित नहीं करता है!):
    1. https://en.cppreference.com/w/cpp/container/span
  2. std::array<T, N>(ध्यान दें कि इसका एक निश्चित आकार है N!):
    1. https://en.cppreference.com/w/cpp/container/array
    2. http://www.cplusplus.com/reference/array/array/
  3. std::vector<T> (स्वचालित रूप से आवश्यक रूप से आकार में बढ़ता है):
    1. https://en.cppreference.com/w/cpp/container/vector
    2. http://www.cplusplus.com/reference/vector/vector/

मैं spanC ++ 11 या बाद में आज कैसे उपयोग कर सकता हूं ?

Google ने अपने आंतरिक सी ++ 11 पुस्तकालयों को अपने "एबसील" पुस्तकालय के रूप में खोला है। इस लाइब्रेरी का उद्देश्य C ++ 14 से C ++ 20 और उससे आगे की सुविधाओं को प्रदान करना है जो C ++ 11 और बाद में काम करते हैं, ताकि आप कल की सुविधाओं का उपयोग कर सकें, आज। वे कहते हैं:

C ++ मानक के साथ संगतता

Google ने कई सार विकसित किए हैं जो या तो मैच करते हैं या C ++ 14, C ++ 17, और उससे आगे की विशेषताओं को मिलाते हैं। इन सार के एबसील संस्करणों का उपयोग करने से आप इन सुविधाओं का उपयोग कर सकते हैं, भले ही आपका कोड C ++ 11 दुनिया में जीवन के लिए अभी तक तैयार नहीं है।

यहां कुछ प्रमुख संसाधन और लिंक दिए गए हैं:

  1. मुख्य साइट: https://abseil.io/
  2. https://abseil.io/docs/cpp/
  3. GitHub रिपॉजिटरी: https://github.com/abseil/abseil-cpp
  4. span.hहेडर और absl::Span<T>(array, length)टेम्प्लेट क्लास: https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h#L189

1
मुझे लगता है कि आप महत्वपूर्ण और उपयोगी जानकारी लाते हैं, धन्यवाद!
गुई लीमा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.