प्रतिनिधि इंटरव्यू विषय

C++ इंटरव्यू: std::inplace_vector की निश्चित क्षमता डिज़ाइन को कैसे बदलती है?

कोडिंगकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

बताएं कि C++26 std::inplace_vector<T, N> ऑब्जेक्ट के भीतर निश्चित-क्षमता वाले निरंतर (contiguous) स्टोरेज के साथ परिवर्तनीय लंबाई कैसे प्रदान करता है। ओवरफ्लो, अपवादों (exceptions), मूव्स, इटरेटर अमान्यीकरण, और किन स्थितियों में std::vector सही विकल्प बना रहता है, इसे कवर करने वाली एक सुरक्षित अपेंड नीति डिज़ाइन करें।

प्रॉम्प्ट और दायरा

बताएं कि C++26 std::inplace_vector<T, N> ऑब्जेक्ट के भीतर निश्चित-क्षमता वाले निरंतर स्टोरेज के साथ परिवर्तनीय लंबाई कैसे प्रदान करता है। ओवरफ्लो, अपवादों, मूव्स, इटरेटर अमान्यीकरण, और किन स्थितियों में std::vector सही विकल्प बना रहता है, इसे कवर करने वाली एक सुरक्षित अपेंड नीति डिज़ाइन करें।

std::inplace_vector एक C++26 निरंतर कंटेनर है जिसका आकार बदलता रहता है जबकि स्टोरेज ऑब्जेक्ट के अंदर रहता है और क्षमता गैर-प्रकार टेम्पलेट पैरामीटर (non-type template parameter) N द्वारा निश्चित होती है। यह एक ज्ञात ऊपरी सीमा और नो-एलोकेशन पथ के लिए उपयुक्त है, लेकिन यह std::array नहीं है और असीमित रूप से नहीं बढ़ सकता है। उत्तर सिंटैक्स के बजाय क्षमता अनुबंधों और ऑब्जेक्ट लाइफ़टाइम पर केंद्रित होना चाहिए।

साक्षात्कारकर्ता क्या मूल्यांकन करता है

  • आकार, क्षमता, इन-ऑब्जेक्ट स्टोरेज और डायनेमिक एलोकेशन को अलग-अलग समझना।
  • क्षमता N पर ओवरफ्लो सिमेंटिक्स और त्रुटि नीति को समझाना।
  • निरंतर स्टोरेज, मूव्स, संदर्भों (references) और इटरेटर अमान्यीकरण को समझना।
  • एलिमेंट-कंस्ट्रक्शन अपवादों पर चर्चा करना और यह तय करना कि क्या एक मजबूत गारंटी (strong guarantee) संभव है।
  • यह पहचानना कि N ऑब्जेक्ट के आकार, स्टैक लेआउट और ABI को कैसे प्रभावित करता है।
  • inplace_vector, array, vector और अन्य कंटेनरों के बीच सही चुनाव करना।

पूछे जाने वाले स्पष्टीकरण प्रश्न

  1. क्या N एक कंपाइल-टाइम पर सत्यापन योग्य सीमा है या रनटाइम कॉन्फ़िगरेशन है?
  2. क्या ओवरफ्लो एक प्रोग्रामर त्रुटि है, पुनर्प्राप्ति योग्य (recoverable) इनपुट है, या ड्रॉप किया जाने वाला संदेश है?
  3. क्या तत्व मूवेबल, कॉपी करने योग्य, या संभावित रूप से अपवाद फेंकने वाले हैं?
  4. क्या कंटेनर स्टैक, पूल, शेयर्ड मेमोरी, या किसी हॉट-पाथ ऑब्जेक्ट में रहता है?
  5. क्या कॉलर तत्व संदर्भ, पॉइंटर्स, या इटरेटर बनाए रखते हैं?

30-सेकंड का उत्तर

मैं N को एक स्पष्ट क्षमता अनुबंध बनाऊंगा और ओवरफ्लो नीति चुनूंगा—अस्वीकार करना, त्रुटि लौटाना, या बैकप्रेशर लागू करना—कभी भी अंतर्निहित वृद्धि नहीं। inplace_vector निरंतर एक्सेस बनाए रखता है लेकिन अपने बफर को ऑब्जेक्ट में संग्रहीत करता है, इसलिए ऑब्जेक्ट का आकार और मूव लागत N के साथ बढ़ती है। अपेंड करने से पहले आकार की जाँच करें और ऐसे निर्माण पथ का उपयोग करें जो तत्व की अपवाद गारंटियों से मेल खाता हो। हीप रीएलोकेशन न होने पर भी इंसर्शन संदर्भों और इटरेटरों को अमान्य कर सकता है। अज्ञात सीमाओं या परिशोधित (amortized) वृद्धि के लिए, मैं std::vector का उपयोग करूँगा।

चरण-दर-चरण गहन विश्लेषण

1. स्थिति क्षमता और लाइफ़टाइम

std::inplace_vector<T, N> का आकार शून्य और N के बीच होता है, और तत्व निरंतर पतों पर रहते हैं। N प्रकार (type) का हिस्सा है। निर्माण सभी N तत्वों को डिफ़ॉल्ट रूप से निर्मित नहीं करता है; तत्वों का निर्माण इंसर्शन पर होता है और केवल जीवित तत्वों को नष्ट किया जाता है।

2. अपेंड अनुबंध परिभाषित करें

अपेंड करने से पहले size() == capacity() की जाँच करें और ओवरफ्लो को व्यावसायिक त्रुटि, ड्रॉप नीति, या अपस्ट्रीम बैकप्रेशर पर मैप करें। reserve को विस्तार के रूप में न मानें या पिछले हिस्से को चुपचाप ओवरराइट न करें। बैच अपेंड के लिए, या तो पहले शेष क्षमता की जाँच करें या आंशिक सफलता को परिभाषित करें और डाले गए तत्वों की संख्या लौटाएं।

cpp
template<class T, std::size_t N>
bool try_append(std::inplace_vector<T, N>& out, T value) {
  if (out.size() == out.capacity()) return false;
  out.push_back(std::move(value));
  return true;
}

यह उदाहरण केवल क्षमता नीति को व्यक्त करता है। वास्तविक रिटर्न और स्थिति की गारंटी इस बात पर निर्भर करती है कि क्या T का मूव कंस्ट्रक्शन अपवाद फेंक सकता है।

3. अपवाद सुरक्षा संभालें

यदि तत्व निर्माण या मूविंग अपवाद फेंक सकती है, तो कंटेनर इनवेरिएंट्स को बनाए रखें और बताएं कि क्या ऑपरेशन बुनियादी (basic) या मजबूत (strong) गारंटी प्रदान करता है। एक बैच एक अस्थायी कंटेनर में निर्माण कर सकता है और फिर मूव कर सकता है, लेकिन वह मूव भी अपवाद फेंक सकता है; प्रकार का नाम किसी ट्रांज़ैक्शनल कमिट का वादा नहीं करता है।

4. संदर्भों और इटरेटरों पर चर्चा करें

किसी तत्व को सम्मिलित करने से बाद के तत्व स्थानांतरित हो सकते हैं, इसलिए सहेजे गए संदर्भों, पॉइंटर्स और इटरेटरों को मानक अमान्यीकरण नियमों का पालन करना चाहिए। हीप रीएलोकेशन न होने का मतलब यह नहीं है कि स्थितियाँ कभी नहीं बदलती हैं। कॉलर को तत्व पते बनाए रखने के लिए प्रोत्साहित करने के बजाय एक API इंडेक्स या स्थिर हैंडल लौटा सकता है।

5. ऑब्जेक्ट आकार और मूव लागत की तुलना करें

इन-ऑब्जेक्ट बफर का अर्थ है कि sizeof(inplace_vector<T, N>) आम तौर पर N और तत्व संरेखण (alignment) के साथ बढ़ता है। स्टैक फ़्रेम, संदेश ऑब्जेक्ट, या अक्सर कॉपी की जाने वाली संरचना में बड़ी क्षमता रखने से स्टैक, कैश और मूव लागत बढ़ सकती है। यह दावा करने से पहले कि एलोकेशन से बचना हमेशा तेज़ होता है, लेआउट को मापें।

6. विकल्प चुनें

ज्ञात सीमा, निरंतर एक्सेस और बिना एलोकेशन वाले पथ के लिए inplace_vector चुनें। तत्वों की एक निश्चित संख्या के लिए std::array का उपयोग करें, अज्ञात सीमाओं या वृद्धि के लिए std::vector का उपयोग करें, और जब स्थिर नोड पते मायने रखते हों तो किसी अन्य कंटेनर का उपयोग करें। क्षमता, लाइफ़टाइम, लोकैलिटी और त्रुटि सिमेंटिक्स निर्णय लेते हैं।

7. परीक्षण और निरीक्षण करें

रिक्त, बिल्कुल पूर्ण, क्षमता से अधिक, अपवाद फेंकने वाले तत्वों, मूव्स और प्रतियों, नेस्टेड ऑब्जेक्ट्स और बड़े N का परीक्षण करें। ओवरफ्लो काउंट, आंशिक बैच सफलता, ऑब्जेक्ट आकार और हॉट-पाथ लेटेंसी रिकॉर्ड करें; लाइफ़टाइम त्रुटियों के लिए सैनिटाइज़र का उपयोग करें। जब कंपाइलर और लाइब्रेरी C++26 का समर्थन करते हैं, तो फीचर-टेस्ट मैक्रोज़ और कार्यान्वयन अंतरों को सत्यापित करें।

उच्च-गुणवत्ता वाला नमूना उत्तर

मैं N को एक कंपाइल-टाइम क्षमता अनुबंध के रूप में मानूंगा: आकार बदलता रहता है लेकिन N से अधिक नहीं हो सकता, और तत्व ऑब्जेक्ट के अंदर निरंतर होते हैं। अपेंड करने से पहले शेष क्षमता की जाँच करें और ओवरराइट करने के बजाय ओवरफ्लो को त्रुटि या बैकप्रेशर पर मैप करें। संभावित रूप से अपवाद फेंकने वाले तत्वों के लिए बुनियादी या मजबूत गारंटी परिभाषित करें और बताएं कि क्या कोई बैच आंशिक रूप से सफल हो सकता है। केवल इसलिए संदर्भ और इटरेटर स्वतः स्थिर नहीं होते क्योंकि कोई हीप वृद्धि नहीं होती है।

मैं ऑब्जेक्ट के आकार, स्टैक और कैश दबाव, मूव लागत और ABI को भी मापूँगा। एक ज्ञात सीमा और निरंतर हॉट-पाथ एक्सेस के साथ, inplace_vector उपयुक्त हो सकता है; अज्ञात सीमाओं या परिशोधित वृद्धि के लिए, std::vector का उपयोग करें, और एक निश्चित संख्या के लिए std::array का उपयोग करें। क्षमता और अपवाद सीमाओं का परीक्षण करें और ओवरफ्लो तथा लेटेंसी का निरीक्षण करें।

सामान्य गलतियाँ

  • इसे एक ऐसे vector के रूप में मानना जो बढ़ता है → यह N पर रुकता है → ओवरफ्लो सिमेंटिक्स बताएं।
  • यह मान लेना कि इन-ऑब्जेक्ट स्टोरेज संदर्भों को स्थिर रखता है → तत्वों का मूवमेंट स्थितियों को बदलता है → अमान्यीकरण नियमों का पालन करें।
  • यह मान लेना कि सभी तत्वों का निर्माण हो चुका है → केवल वर्तमान आकार ही सक्रिय है → स्टोरेज को लाइफ़टाइम से अलग रखें।
  • ऑब्जेक्ट के आकार को अनदेखा करते हुए शून्य एलोकेशन पर ध्यान केंद्रित करना → बड़ा N स्टैक और कैश पर दबाव डालता है → लेआउट और मूव्स को मापें।
  • यह मान लेना कि बैच अपवाद स्वचालित रूप से रोलबैक हो जाते हैं → तत्व मूव्स अपवाद फेंक सकते हैं → गारंटी बताएं और परीक्षण करें।
  • इसे किसी अज्ञात सीमा पर जबरन लागू करना → व्यावसायिक इनपुट अस्वीकृत या छोटा (truncate) हो जाता है → vector या कोई अन्य कंटेनर चुनें।

फॉलो-अप प्रश्न और उत्तर

inplace_vector<T, N>, std::array<T, N> से किस प्रकार भिन्न है?

इसका आकार शून्य से N तक भिन्न होता है और आवश्यकतानुसार तत्वों का निर्माण किया जाता है; एक array में हमेशा N तत्व होते हैं। दोनों इन-ऑब्जेक्ट स्टोरेज का उपयोग करते हैं, लेकिन उनके लाइफ़टाइम और API अनुबंध भिन्न होते हैं।

क्या पूर्ण क्षमता होने पर अपवाद फेंकना चाहिए?

यह एक व्यावसायिक निर्णय है। पुनर्प्राप्ति योग्य इनपुट आमतौर पर एक त्रुटि लौटाता है या बैकप्रेशर लागू करता है; एक प्रोग्रामर त्रुटि एक असर्शन या अपवाद का उपयोग कर सकती है। चुपचाप ओवरराइट करना अस्वीकार्य है, और बैच आंशिक-सफलता सिमेंटिक्स स्पष्ट होना चाहिए।

जब inplace_vector को मूव किया जाता है तो क्या होता है?

तत्वों को गंतव्य ऑब्जेक्ट के बफर में ले जाया (move) या कॉपी किया जाता है, जिसकी लागत आकार और तत्व के प्रकार से जुड़ी होती है। यह केवल हीप पॉइंटर की अदला-बदली करना नहीं है।

बहुत बड़ा N क्यों न चुनें?

बफर ऑब्जेक्ट, स्टैक, कॉपी और कैश लागत को बढ़ाता है। वास्तविक वितरण, टेल क्षमता और ओवरफ्लो लागत के आधार पर N चुनें।

क्या होगा यदि मानक लाइब्रेरी में C++26 समर्थन का अभाव है?

फ़ीचर-टेस्ट मैक्रोज़ और कार्यान्वयन दस्तावेज़ों की जाँच करें, एक स्पष्ट बिल्ड आवश्यकता सेट करें या कोई विकल्प चुनें। किसी प्रयोगात्मक कार्यान्वयन को चुपचाप मानक व्यवहार न मानें।

आप तत्व संदर्भों को कैसे सुरक्षित रखते हैं?

संदर्भ लाइफ़टाइम को सीमित करें, इंडेक्स या स्थिर हैंडल को प्राथमिकता दें, और इंसर्शन, मूव्स या विनाश के बाद पुराने संदर्भों को प्रतिबंधित करें। सैनिटाइज़र और सीमा परीक्षणों के साथ सत्यापन करें।

सार्वजनिक स्रोत

संबंधित प्रश्न

संबंधित इंटरव्यू टूल

कोडिंग प्रॉम्प्ट के लिए स्क्रीनशॉट का उपयोग करें

समस्या को कैप्चर करें, फिर क्रम से प्रतिबंधों (constraints), समाधान, कोड, एज केस और जटिलता पर काम करें।

टूल देखें