2013-03-11 5 views
11

मुझे एक बार नौकरी साक्षात्कार में एक चाल प्रश्न पूछा गया था: क्या एक टेम्पलेटेड क्लास एक और वर्ग की तुलना में अधिक स्मृति लेती है जो समान है लेकिन टेम्पलेट नहीं है? मेरा जवाब नहीं था, लेकिन तथ्य यह है कि उसने सवाल पूछा कि शायद वहां एक मामला है जहां वहां है। या, वह वास्तव में मेरे साथ पेंच करना चाहता था। एक ऐसा मामला क्या होगा जहां एक टेम्पलेटेड कक्षा अधिक स्मृति लेगी?एक टेम्पलेट श्रेणी गैर-टेम्पलेट वर्ग से समान प्रकार का उपयोग कर बड़ी है?

+7

मुझे संदेह है कि तथ्य यह है कि उन्होंने सवाल पूछा कि ऐसे लोग हैं जो सोचते हैं * एक वर्ग टेम्पलेट गैर-टेम्पलेट वर्ग की तुलना में अधिक स्मृति लेता है। –

+2

नहीं, यह नहीं है। यह बिल्कुल वही लेता है। –

+0

हां, 'क्लास टेम्पलेट' सामान्य वर्ग की तुलना में अधिक मेमोरी लेता है, लेकिन यह स्रोत फ़ाइल में है क्योंकि अधिक टेक्स्ट की आवश्यकता है। – iammilind

उत्तर

15

पहली बात यह स्पष्ट कर रही है कि सवाल का अर्थ क्या है। यदि सवाल यह है कि इस प्रकार की वस्तुएं बड़ी होंगी (यानी sizeof(T<int>) > sizeof(T_int)) तो उत्तर नहीं है। यदि प्रश्न एप्लिकेशन के बाइनरी पदचिह्न के बारे में है, तो कार्यों के लिए कोड सहित, तो जवाब यह है कि प्रोग्राम का समग्र आकार वास्तव में टेम्पलेट के मामले में छोटा हो सकता है क्योंकि केवल प्रयुक्त सदस्य कार्य होंगे संकलित (जब तक स्पष्ट रूप से तत्काल नहीं)। हालांकि दिन के अंत में, लिंकर अप्रयुक्त सदस्यों को गैर-टेम्पलेट संस्करण से भी हटा सकता है।

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

एक सदिश टेम्पलेट के लिए एक संभावित इंटरफेस पर विचार करें:

template <typename T> 
class Vector { 
    template <typename U> void push_back(U u); 
//.... 

एक अलग तर्क प्रकार के साथ push_back के लिए हर कॉल के लिए, एक नया कार्य, उत्पन्न हो जाएगा तो Vector<int>::push_back('a') के लिए एक समारोह और के लिए एक दूसरे से नहीं होगा Vector<int>::push_back(1)। तुलना करें कि std::vector के इंटरफ़ेस के साथ जिसमें सदस्य फ़ंक्शन टेम्पलेट नहीं है और कॉलर प्रकार रूपांतरण करता है।

हालांकि यह बड़े निष्पादन योग्य स्रोतों का स्रोत हो सकता है, मैं इस पर विचार नहीं करता कि इसके लिए क्या पूछा गया था। विशेष रूप से, एक टेम्पलेट प्रकार के लिए, और समकक्ष गैर-टेम्पलेट प्रकार के लिए विशेष तत्काल प्रकार के लिए हस्तनिर्मित, जेनरेट कोड समकक्ष होना चाहिए (इस तथ्य को अनदेखा करना कि मैग्लेड नाम टेम्पलेट्स के लिए बड़े होते हैं :))

+0

+1 अच्छा जवाब। लगभग सभी बिंदु समझाया। – Nawaz

+0

@ नवाज: मैंने अभी अंतिम निष्पादन योग्य (इंटरमीडिएट स्तर पर, टेम्पलेट के लिए कोड को जोड़ने से पहले कोड को प्रत्येक अनुवाद इकाई में एक ही सदस्य फ़ंक्शंस की कई परिभाषाओं के बारे में सोचने पर विचार किया था, लेकिन उन्हें लिंक समय पर छोड़ दिया गया था)। यदि आपके पास * लगभग सभी * को पूरा करने के लिए कुछ और है, तो मुझे उनकी सुनवाई में दिलचस्पी है :) –

+0

नहीं। मेरे पास मेरे दिमाग में कुछ और नहीं है। आपने बहुत कुछ कहा जो मैं सोच सकता था (अभी तक)। मैंने ठीक उसी कारण से "लगभग सभी" कहा था, मैंने "सब" नहीं कहा था। मुझे लगता है कि संभावनाओं के लिए खुला होना बुद्धिमानी है। :-) – Nawaz

5

उत्तर नहीं है, जहां तक ​​स्मृति का संबंध है। मेरा मतलब है, यह आवश्यक रूप से अधिक स्मृति लेना नहीं है, हालांकि कुछ बुराई व्यक्ति को साबित करने के लिए सिर्फ एक वर्ग टेम्पलेट लिख सकता है, उसके बिंदु कि क्लास टेम्पलेट संस्करण अधिक मेमोरी लेता है।

हालांकि, प्रकार पैरामीटर के किसी विशेष मान (ओं) के लिए गैर-टेम्पलेट क्लैस संस्करणों की तुलना में कक्षा टेम्पलेट का स्रोत कोड बड़ा (या उस मामले के लिए कम) हो सकता है।

template<typename T> 
struct point_t 
{ 
    T x, y, z; 
}; 

struct point_int 
{ 
    int x, y, z; 
}; 

std::cout << (sizeof(point_int) == sizeof(point_t<int>)) << std::end; 

यह true (या 1) प्रिंट होगा।

ध्यान दें कि point_int और point_t<int> का मेमोरी लेआउट समान होगा। तो अगर आप भी इस तरह डाली कर सकते हैं:

point_t<int> pt {10, 20, 30}; 

point_int pi = *reinterpret_cast<point_int*>(&pt); 

std::cout << "{" << pi.x <<"," << pi.y <<"," << pi.z << "}" << std::endl; 

यह {10, 20, 30} प्रिंट होगा।

आशा में मदद करता है।

2

टेम्पलेट को संकलित समय पर हर जगह वास्तविक मूल्यों के साथ प्रतिस्थापित किया जाता है। इसलिए यदि आप एक टेम्पलेट वर्ग है कहते हैं:

public List<T> 
{ 
    public T* MyT; 
    ... 
} 

और अपने कोड एक विशिष्ट प्रकार के साथ इसे इस्तेमाल करता है कहते हैं: सूची, की तुलना में वास्तव में क्या हो रहा है कि इस कोड को प्रयोग किया जाता है:

public List<Point> 
{ 
public Point *MyT; 
.... 
} 

तो यह किसी अन्य गैर-टेम्पलेट वर्ग के समान आकार का सार है।

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