खोज…


टिप्पणियों

कीवर्ड auto एक टाइपनेम है जो स्वचालित रूप से कटौती प्रकार का प्रतिनिधित्व करता है।

यह C ++ 98 में पहले से ही एक आरक्षित कीवर्ड था, C से विरासत में मिला। C ++ के पुराने संस्करणों में, यह स्पष्ट रूप से बताया जा सकता है कि एक चर में स्वचालित भंडारण अवधि है:

int main()
{
  auto int i = 5; // removing auto has no effect
}

वह पुराना अर्थ अब हटा दिया गया है।

मूल ऑटो नमूना

कीवर्ड auto एक चर के प्रकार के ऑटो-कटौती प्रदान करता है।

यह लंबे प्रकार के नामों से निपटने के दौरान विशेष रूप से सुविधाजनक है:

std::map< std::string, std::shared_ptr< Widget > > table;
// C++98
std::map< std::string, std::shared_ptr< Widget > >::iterator i = table.find( "42" );
// C++11/14/17
auto j = table.find( "42" );

सीमा-आधारित छोरों के साथ :

vector<int> v = {0, 1, 2, 3, 4, 5};
for(auto n: v)
    std::cout << n << ' ';

लंबोदर के साथ:

auto f = [](){ std::cout << "lambda\n"; };
f();        

प्रकार की पुनरावृत्ति से बचने के लिए:

auto w = std::make_shared< Widget >();

आश्चर्यजनक और अनावश्यक प्रतियों से बचने के लिए:

auto myMap = std::map<int,float>();
myMap.emplace(1,3.14);

std::pair<int,float> const& firstPair2 = *myMap.begin();  // copy!
auto const& firstPair = *myMap.begin();  // no copy!

प्रतिलिपि का कारण यह है कि लौटा हुआ प्रकार वास्तव में std::pair<const int,float> !

ऑटो और अभिव्यक्ति टेम्पलेट्स

auto भी समस्याएं पैदा कर सकता है जहां अभिव्यक्ति टेम्पलेट खेल में आते हैं:

auto mult(int c) {
    return c * std::valarray<int>{1};
}

auto v = mult(3);
std::cout << v[0]; // some value that could be, but almost certainly is not, 3.

इसका कारण यह है कि valarray पर operator* आपको एक प्रॉक्सी ऑब्जेक्ट देता है जो valarray को आलसी मूल्यांकन के साधन के रूप में संदर्भित करता है। auto का उपयोग करके, आप एक झूलने वाला संदर्भ बना रहे हैं। mult बजाय एक std::valarray<int> वापस कर दिया था, तो कोड निश्चित रूप से 3 प्रिंट करेगा।

ऑटो, कास्ट, और संदर्भ

auto कीवर्ड अपने आप में एक मान प्रकार का प्रतिनिधित्व करता है, जो int या char समान है। इसे क्रमशः एक कास्ट प्रकार या एक संदर्भ प्रकार का प्रतिनिधित्व करने के लिए const कीवर्ड और & सिंबल के साथ संशोधित किया जा सकता है। ये संशोधक संयुक्त हो सकते हैं।

इस उदाहरण में, s एक मान प्रकार है (इसका प्रकार std::string रूप में अनुमान लगाया जाएगा), इसलिए लूप के for प्रत्येक पुनरावृत्ति वेक्टर से एक स्ट्रिंग को s में कॉपी करता है।

std::vector<std::string> strings = { "stuff", "things", "misc" };
for(auto s : strings) {
    std::cout << s << std::endl;
}

यदि लूप का शरीर s को संशोधित करता है (जैसे कि s.append(" and stuff") को कॉल s.append(" and stuff") ), तो केवल इस प्रति को संशोधित किया जाएगा, न कि strings के मूल सदस्य को।

दूसरी ओर, यदि auto& साथ s घोषित किया गया है auto& यह एक संदर्भ प्रकार होगा (अनुमान std::string& ), तो लूप के प्रत्येक पुनरावृत्ति पर इसे वेक्टर में एक स्ट्रिंग के संदर्भ में सौंपा जाएगा:

for(auto& s : strings) {
    std::cout << s << std::endl;
}

इस लूप के शरीर में, के लिए संशोधन s सीधे के तत्व को प्रभावित करेगा strings कि यह संदर्भ।

अंत में, यदि s को const auto& घोषित किया जाता है, तो यह एक कॉन्स्ट रेफरेंस टाइप होगा, जिसका अर्थ है कि लूप के प्रत्येक पुनरावृत्ति पर इसे वेक्टर में एक स्ट्रिंग के लिए एक कॉन्स्ट रेफरेंस सौंपा जाएगा:

for(const auto& s : strings) {
    std::cout << s << std::endl;
}

इस लूप के शरीर के भीतर, s को संशोधित नहीं किया जा सकता है (अर्थात इस पर कोई गैर-कास्ट तरीके नहीं कहा जा सकता है)।

जब लूप्स के for रेंज-आधारित के साथ auto का उपयोग करते हैं, तो आमतौर पर const auto& का उपयोग करना अच्छा होता है const auto& अगर लूप बॉडी को लूप किए जाने वाले ढांचे को संशोधित नहीं किया जाएगा, क्योंकि यह अनावश्यक प्रतियों से बचा जाता है।

अनुगामी वापसी प्रकार

auto का उपयोग सिंटैक्स में रिटर्न रिटर्न प्रकार के लिए किया जाता है:

auto main() -> int {}

के बराबर है

int main() {}

decltype बजाय मापदंडों का उपयोग करने के लिए decltype के साथ संयुक्त रूप से उपयोगी decltype std::declval<T> :

template <typename T1, typename T2>
auto Add(const T1& lhs, const T2& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }

जेनेरिक लैम्ब्डा (C ++ 14)

सी ++ 14

C ++ 14 लैम्ब्डा तर्क में auto का उपयोग करने की अनुमति देता है

auto print = [](const auto& arg) { std::cout << arg << std::endl; };

print(42);
print("hello world");

वह लंबोदर ज्यादातर बराबर है

struct lambda {
    template <typename T>
    auto operator ()(const T& arg) const {
        std::cout << arg << std::endl;
    }
};

और फिर

lambda print;

print(42);
print("hello world");

ऑटो और प्रॉक्सी ऑब्जेक्ट

कभी-कभी auto काफी व्यवहार नहीं कर सकता जैसा कि एक प्रोग्रामर द्वारा अपेक्षित था। यह टाइप अभिव्यक्ति को घटाता है, तब भी जब टाइप कटौती सही काम नहीं है।

एक उदाहरण के रूप में, जब कोड में प्रॉक्सी ऑब्जेक्ट का उपयोग किया जाता है:

std::vector<bool> flags{true, true, false};
auto flag = flags[0];
flags.push_back(true);

यहाँ flag bool नहीं होगा, लेकिन std::vector<bool>::reference , क्योंकि टेम्पलेट vector के bool विशेषज्ञता के लिए operator [] रूपांतरण ऑपरेटर operator bool परिभाषित के साथ एक प्रॉक्सी वस्तु देता है।

जब flags.push_back(true) कंटेनर को संशोधित करता है, तो यह छद्म संदर्भ एक तत्व का जिक्र करते हुए झूलने को समाप्त कर सकता है जो अब मौजूद नहीं है।

यह अगली स्थिति को भी संभव बनाता है:

void foo(bool b);

std::vector<bool> getFlags();

auto flag = getFlags()[5];
foo(flag);

vector को तुरंत खारिज कर दिया vector है, इसलिए flag एक तत्व के लिए एक छद्म संदर्भ है जिसे त्याग दिया गया है। foo को कॉल अपरिभाषित व्यवहार को आमंत्रित करता है।

इस तरह के मामलों में आप auto साथ एक वैरिएबल की घोषणा कर सकते हैं और इसे उस प्रकार के कास्टिंग के द्वारा आरंभ कर सकते हैं जिसे आप कम करना चाहते हैं:

auto flag = static_cast<bool>(getFlags()[5]);

लेकिन उस बिंदु पर, बस bool साथ auto जगह अधिक समझ में आता है।

एक अन्य मामला जहां प्रॉक्सी ऑब्जेक्ट समस्या पैदा कर सकता है वह है अभिव्यक्ति टेम्पलेट । उस स्थिति में, टेम्प्लेट कभी-कभी दक्षता पूर्णता के लिए वर्तमान पूर्ण-अभिव्यक्ति से परे रहने के लिए डिज़ाइन नहीं किए जाते हैं और प्रॉक्सी ऑब्जेक्ट का उपयोग अपरिभाषित व्यवहार के कारण होता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow