क्या वैक्टर C ++ में मूल्य के आधार पर या संदर्भ के आधार पर किए गए हैं


94

मैं C ++ में कोडिंग कर रहा हूं। यदि मेरे पास कुछ फ़ंक्शन है void foo(vector<int> test)और मैं इसे अपने कार्यक्रम में बुलाता हूं, तो क्या वेक्टर को मूल्य या संदर्भ से पारित किया जाएगा? मैं अनिश्चित हूँ क्योंकि मुझे पता है कि वैक्टर और सरणियाँ समान हैं और यह एक फ़ंक्शन की तरह फ़ंक्शन void bar(int test[])मान के बजाय संदर्भ (पॉइंटर) द्वारा परीक्षण पास करेगा। मेरा अनुमान है कि यदि मुझे मूल्य से गुजरने से बचना है तो मुझे सूचक / संदर्भ द्वारा वेक्टर को पास करना होगा, लेकिन मुझे यकीन नहीं है।


5
C ++ में "पास बाय वैल्यू" शब्दार्थ है, इसलिए इसे वैल्यू द्वारा पास किया जाता है। आप संदर्भ द्वारा पारित करने का निर्णय ले सकते हैं। चुनाव वास्तव में इस बात पर निर्भर करता है कि फ़ंक्शन क्या करता है।
जुआनकोपंजा

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

3
इसके अलावा, एक संदर्भ एक सूचक नहीं है।
पैरामैग्नेटिक क्रोइसैंट

2
@AliKazmi अगर आप फंक्शन की बॉडी में कॉपी चाहते हैं।
जुआनकोपंजा

यह इस बात पर निर्भर करता है कि आप क्या हासिल करना चाहते हैं। एक मानक स्मार्ट पॉइंटर्स का उपयोग करना कभी-कभी उपयोगी होता है, उदाहरण के लिए यदि आप स्वामित्व पर पास करना चाहते हैं, तो अनूठे_ptr का उपयोग करें। लेकिन आमतौर पर, मैं संदर्भ से एसटीडी: वेक्टर पास करता हूं।
एरिक अलापा

जवाबों:


134

अगर मुझे अनुमान लगाना होता, तो मैं कहता कि आप एक जावा बैकग्राउंड से हैं। यह सी ++ है, और चीजें तब तक मूल्य से पारित हो जाती हैं जब तक कि आप अन्यथा निर्दिष्ट न करें &-परेटर का उपयोग करें (ध्यान दें कि इस ऑपरेटर को 'एड्रेस-ऑफ' ऑपरेटर के रूप में भी उपयोग किया जाता है, लेकिन एक अलग संदर्भ में)। यह सब अच्छी तरह से प्रलेखित है, लेकिन मैं फिर से पुन: पुनरावृति करूंगा:

void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference

आप एक सदिश ( void foo(vector<int> *bar)) को पॉइंटर पास करने का विकल्प भी चुन सकते हैं , लेकिन जब तक आप यह नहीं जानते कि आप क्या कर रहे हैं और आपको लगता है कि यह वास्तव में जाने का तरीका है, ऐसा न करें।

इसके अलावा, वैक्टर सरणियों के समान नहीं हैं ! आंतरिक रूप से, वेक्टर एक सरणी का ट्रैक रखता है जिसमें से यह आपके लिए मेमोरी प्रबंधन को संभालता है, लेकिन कई अन्य एसटीएल कंटेनर करते हैं। आप एक वेक्टर को एक सूचक या सरणी या इसके विपरीत की अपेक्षा वाले फ़ंक्शन को पास नहीं कर सकते हैं (आप अंतर्निहित सरणी तक (पॉइंटर तक पहुंच प्राप्त कर सकते हैं) और इसका उपयोग कर सकते हैं)। वेक्टर्स अपने सदस्य-फ़ंक्शंस के माध्यम से बहुत अधिक कार्यक्षमता प्रदान करते हैं, जबकि पॉइंटर्स और एरेज़ बिल्ट-इन प्रकार के होते हैं। इसके अलावा, वैक्टर गतिशील रूप से आवंटित किए जाते हैं (जिसका अर्थ है कि आकार निर्धारित किया जा सकता है और रनटाइम में बदला जा सकता है) जबकि सी-स्टाइल सरणियों को सांख्यिकीय रूप से आवंटित किया गया है (इसका आकार स्थिर है और संकलन-समय पर ज्ञात होना चाहिए), उनके उपयोग को सीमित करना।

मेरा सुझाव है कि आप सामान्य रूप से C ++ के बारे में कुछ और पढ़ें (विशेष रूप से सरणी क्षय ), और फिर निम्नलिखित कार्यक्रम पर एक नज़र डालें जो सरणियों और बिंदुओं के बीच के अंतर को दिखाता है:

void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    foo1(arr);
    foo2(arr);
    foo3(arr);
    foo4(arr);
}

2
क्या कोई मुझे अंतिम घोषणा foo4 फ़ंक्शन को समझने में मदद कर सकता है? यह अन्य कार्यों की तरह सूचक के आकार के बजाय सरणी का आकार क्यों लौटाता है?
abhishek_M

3
@abhishek_M क्योंकि पैरामीटर प्रकार एक संदर्भ है। एक संदर्भ केवल उसी प्रकार की अभिव्यक्ति के लिए बाध्य हो सकता है। इस कारण से सरणी का क्षय नहीं होता है, क्योंकि किसी सरणी का संदर्भ सूचक के लिए बाध्य नहीं हो सकता है, यह केवल उसी प्रकार के सरणी के लिए बाध्य हो सकता है (इस मामले में 10 पूर्णांक के सरणी)
bolov

1
c ++ 11 में "मूव सिमेंटिक्स" है और आप इसे बिना कॉपी के वैल्यू (मूव सिमेंटिक्स) के साथ सावधानीपूर्वक और पास कर सकते हैं। यहाँ एक लिंक है जिसने मुझे बहुत मदद की: mbevin.wordpress.com/2012/11/20/move-semantics
fchen

23

A vectorकार्यात्मक रूप से एक सरणी के समान है। लेकिन, भाषा vectorएक प्रकार है, और intएक प्रकार भी है। फ़ंक्शन तर्क के लिए, किसी भी प्रकार (सहित vector[]) की एक सरणी को पॉइंटर के रूप में माना जाता है। एक vector<int>के समान नहीं है int[](संकलक के लिए)। vector<int>गैर-सरणी, गैर-संदर्भ और गैर-पॉइंटर है - इसे मूल्य से पारित किया जा रहा है, और इसलिए इसे कॉपी-कंस्ट्रक्टर कहेंगे।

इसलिए, आपको इसे संदर्भ के रूप में पास करने के लिए vector<int>&(अधिमानतः const, यदि फ़ंक्शन इसे संशोधित नहीं कर रहा है) का उपयोग करना चाहिए ।


एक फ़ंक्शन के संदर्भ में "वैक्टर के एक सरणी" को पारित करने के लिए वाक्यविन्यास क्या है?
13:123


9

void foo(vector<int> test)

इसमें सदिश मूल्य से पारित किया जाएगा।

आपके पास संदर्भ के आधार पर वैक्टर पास करने के अधिक तरीके हैं: -

1) संदर्भ से गुजारें: - यह फ़ंक्शन फू को वेक्टर की अपनी सामग्री को बदलने देगा। सदिश की नकल के रूप में मूल्य से अधिक कुशल पास से बचा जाता है।

2) कॉन्स्टेंस-रेफरेंस द्वारा पास करें: - यह सदिश की सामग्री को बदलने के लिए फंक्शन न चाहते हुए भी कुशल और विश्वसनीय है।


1

जब हम किसी फ़ंक्शन में वेक्टर को एक तर्क के रूप में पास करते हैं, तो यह केवल वेक्टर की प्रतिलिपि बनाता है और वेक्टर पर कोई प्रभाव नहीं पड़ता है जो मुख्य फ़ंक्शन में परिभाषित होता है जब हम उस विशेष फ़ंक्शन को कहते हैं। जब हम वेक्टर को उस विशेष फ़ंक्शन में लिखे गए संदर्भ के माध्यम से पास करते हैं, तो हर क्रिया वेक्टर पर प्रदर्शन करने जा रही है जिसे मुख्य या अन्य फ़ंक्शन में परिभाषित किया जाता है जब हम उस विशेष फ़ंक्शन को कहते हैं।

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