2011-10-17 15 views
6

में पॉइंटर को क्षय का क्षय क्यों करता है मुझे समझ में नहीं आता कि सरणी टेम्पलेट फ़ंक्शन में पॉइंटर का कारण क्यों है।सरणी टेम्पलेट फ़ंक्शन

यदि आप निम्न कोड को देखते हैं: जब पैरामीटर को संदर्भ (फ़ंक्शन f1) होने के लिए मजबूर किया जाता है तो यह क्षय नहीं होता है। दूसरे समारोह में यह decays। फंक्शन में टी का प्रकार एफ क्यों नहीं है (buff &) [3] बल्कि इसके बजाय चार * (यदि मैं इसे सही ढंग से समझता हूं)?

#include <iostream> 

template <class T> 
void f(T buff) { 
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;  //prints 4 
} 

template <class T> 
void f1(T& buff) { 
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;  //prints 3 
} 

int main(int argc, char *argv[]) { 
    const char buff[3] = {0,0,0}; 
    std::cout << "buff size:" << sizeof(buff) << std::endl;   //prints 3 
    f(buff); 
    f1(buff); 
    return 0; 
} 
+0

यदि आप बस एक ' टी' से 'एफ', फिर' टी' 'int 'होगा,' int' 'नहीं। इसलिए, आपको कुछ पूछना चाहिए "फ़ंक्शन में टी का प्रकार क्यों नहीं है 'char [3]' बल्कि' const char * '? ' (अपने उत्तर की तुलना में लापता '&' को नोट करें) –

+0

... (मेरी अंतिम टिप्पणी से फ़ॉलो करें)। सी/सी ++ भाषा के बारे में सबसे बेवकूफ बात यह है कि यदि आप अपने पैरामीटर में 'कॉन्स्ट चार [3]' डालते हैं, तो संकलक चुपचाप इसे 'कॉन्स्ट char *' के रूप में फिर से लिख देगा। यह स्थानीय चर के साथ नहीं होता है, उदाहरण के लिए। मुझे सच में लगता है कि इससे आजकल चेतावनियां होनी चाहिए (कम से कम सी ++ कंपाइलर्स से) –

उत्तर

7

क्योंकि सरणी को फ़ंक्शन पैरामीटर के रूप में मान द्वारा पारित नहीं किया जा सकता है।
जब आप उन्हें मूल्य से पास करते हैं तो वे एक सूचक में क्षय हो जाते हैं।

इस समारोह में:

template <class T> 
void f(T buff) { 

टी char (&buff)[3] इस रूप में नहीं किया जा सकता एक संदर्भ है। कंपाइलर ने मूल्य से गुजरने के लिए char (buff)[3] को आजमाया होगा लेकिन इसकी अनुमति नहीं है। तो इसे पॉइंटर्स को एरे क्षय कार्य करने के लिए।

आपकी दूसरी समारोह काम करता है क्योंकि यहाँ सरणी संदर्भ द्वारा पारित कर दिया है:

template <class T> 
void f1(T& buff) { 

// Here T& => char (&buff)[3] 
+0

मेरा मानना ​​है कि वे मूल्य से पारित नहीं होने का कारण कॉपी/असाइनमेंट की कमी से संबंधित हैं। (हालांकि यह सब गायब क्यों है मेरे बाहर है) –

+0

@MooingDuck: C++ में कारण यह है कि विशेष व्यवहार सी से सी विरासत में मिला था। कारण अलग होगा ... –

+1

@MooingDuck: और निश्चित रूप से यह एक है उन चीजों में से जो 'std :: array <> 'कच्चे सी-एरे से तुरंत बेहतर होते हैं। – ildjarn

1

क्योंकि कार्यों तर्कों के रूप सरणियों नहीं हो सकता। हालांकि वे सरणी संदर्भ हो सकते हैं।

1

विभिन्न अधिभारों से मेल खाते समय मूल रूप से कटौती टाइप करने का कारण उबालता है। जब आप f पर कॉल करते हैं तो संकलक const char[3] होने के लिए प्रकार को घटा देता है जो तब const char* में होता है जो करता है। यह उसी सटीक तरीके से किया जाता है कि f(1) में कंपाइलर टी को int और int& नहीं करता है।

f1 के मामले में तर्क के संदर्भ में तर्क लिया जाता है, तो संकलक फिर से टी को const char[3] मानता है, लेकिन इसका संदर्भ लेता है।

कुछ भी नहीं है वास्तव में आश्चर्य की बात है, बल्कि लगातार अगर यह सरणियों के क्षय संकेत करने के लिए जब समारोह तर्क के रूप में इस्तेमाल नहीं थे ...

0

f1() में, आकार 4 सूचक जो 4 बाइट्स का आकार है। क्योंकि इस फ़ंक्शन में आपके पास सरणी के लिए पॉइंटर है।

f1() में, आपके पास संदर्भ (या कोई अन्य नाम) द्वारा उस सरणी है, और यह वास्तविक सरणी आकार है।

4

कल्पना से बोली के लिए, यह कहते हैं

(14.8.2.1/2) तो पी एक संदर्भ प्रकार नहीं है: - यदि एक एक सरणी प्रकार, सूचक सरणी-टू द्वारा उत्पादित प्रकार है -इंटर मानक रूपांतरण (4.2) ए के प्रकार के कटौती के लिए उपयोग किया जाता है; अन्यथा

तो, आपके मामले में, यह स्पष्ट है कि,

template <class T> 
void f1(T& buff) { 
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;  //prints 3 
} 

सूचक में क्षय नहीं होता है।

5

ऐसा इसलिए है क्योंकि सरणीको द्वारा किसी फ़ंक्शन में पारित नहीं किया जा सकता है। तो इसे काम करने के लिए, सरणी एक सूचक में क्षीण हो जाती है जो तब पर पर फ़ंक्शन को पास कर देती है।

दूसरे शब्दों में, मूल्य से एक सरणी गुजर आरंभ एक और सरणी के साथ एक सरणी के लिए समान है, लेकिन C++ एक सरणीएक और सरणी के साथ आरंभ नहीं किया जा सकता है:

char buff[3] = {0,0,0}; 
char x[3] = buff; //error 

तो अगर

char *y = buff; //ok - pointer 
char (&z)[3] = buff; //ok - reference 
: एक सरणी = के दाहिने हाथ की ओर दिखाई देता है, छोड़ दिया हाथ की ओर या तो pointer या reference प्रकार हो गया है (ध्यान दें कि auto साथ सी ++ 11 आता है) http://www.ideone.com/BlfSv

यह इसी कारण auto के लिए ठीक है नीचे प्रत्येक मामले में अलग ढंग से अनुमानित है:

डेमो

auto a = buff; //a is a pointer - a is same as y (above) 
std::cout << sizeof(a) << std::endl; //sizeof(a) == sizeof(char*) 

auto & b = buff; //b is a reference to the array - b is same as z (above) 
std::cout << sizeof(b) << std::endl; //sizeof(b) == sizeof(char[3]) 

आउटपुट:

4 //size of the pointer 
3 //size of the array of 3 chars 

डेमो: http://www.ideone.com/aXcF5

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