C++11: Difference between revisions
From Vigyanwiki
No edit summary |
No edit summary |
||
| Line 31: | Line 31: | ||
सी ++ 03 के साथ ऐसी पुरानी प्रदर्शन करने वाली समस्या के लिए महंगी हैं और अनावश्यक [[गहरी प्रति|डीप लैंग्वेज]] है जो वस्तुओं को मूल्य से पारित होने पर अंतर्निहित रूप से हो सकती है। इस मुद्दे को स्पष्ट करने के लिए, विचार करें कि a <code>std::vector<T></code> आंतरिक रूप से, परिभाषित आकार के साथ सी-शैली सरणी के चारों ओर आवरण करती हैं। यदि <code>std::vector<T></code> अस्थायी बनाया जाता है या किसी फ़ंक्शन से लौटाया जाता है, इसे केवल एक नया बनाकर संग्रहीत किया जा सकता है, इस प्रकार <code>std::vector<T></code> और इसमें सभी आर वैल्यू के डेटा को कॉपी करना आवश्यक होता हैं। इस स्थिति में अस्थायी और उसकी सभी स्मृतियों को यह नष्ट कर देती हैं। (सरलता के लिए, यह वैरियेबल्चा [[वापसी मूल्य अनुकूलन]] की उपेक्षा करती है।) | सी ++ 03 के साथ ऐसी पुरानी प्रदर्शन करने वाली समस्या के लिए महंगी हैं और अनावश्यक [[गहरी प्रति|डीप लैंग्वेज]] है जो वस्तुओं को मूल्य से पारित होने पर अंतर्निहित रूप से हो सकती है। इस मुद्दे को स्पष्ट करने के लिए, विचार करें कि a <code>std::vector<T></code> आंतरिक रूप से, परिभाषित आकार के साथ सी-शैली सरणी के चारों ओर आवरण करती हैं। यदि <code>std::vector<T></code> अस्थायी बनाया जाता है या किसी फ़ंक्शन से लौटाया जाता है, इसे केवल एक नया बनाकर संग्रहीत किया जा सकता है, इस प्रकार <code>std::vector<T></code> और इसमें सभी आर वैल्यू के डेटा को कॉपी करना आवश्यक होता हैं। इस स्थिति में अस्थायी और उसकी सभी स्मृतियों को यह नष्ट कर देती हैं। (सरलता के लिए, यह वैरियेबल्चा [[वापसी मूल्य अनुकूलन]] की उपेक्षा करती है।) | ||
C++11 में, ab:More C++ Idioms/Move Constructor या {{visible anchor|मूव कंस्ट्रक्टर}}का <code>std::vector<T></code> जो इसके लिए प्रतिद्वंद्विता संदर्भ लेता है इस प्रकार <code>std::vector<T></code> किसी नई आरवैल्यू से आंतरिक सी-शैली सरणी में पॉइंटर को कॉपी कर सकते हैं, इसके बाद <code>std::vector<T></code> पुनः पॉइंटर को आर वैल्यू के अंदर शून्य पर सेट करते हैं। चूंकि अस्थायी रूप से ये उपयोग नहीं किया जाएगा, कोई भी कोड अशक्त सूचक तक पहुंचने का प्रयास नहीं करेगा, और क्योंकि सूचक शून्य है, जब यह | C++11 में, ab:More C++ Idioms/Move Constructor या {{visible anchor|मूव कंस्ट्रक्टर}}का <code>std::vector<T></code> जो इसके लिए प्रतिद्वंद्विता संदर्भ लेता है इस प्रकार <code>std::vector<T></code> किसी नई आरवैल्यू से आंतरिक सी-शैली सरणी में पॉइंटर को कॉपी कर सकते हैं, इसके बाद <code>std::vector<T></code> पुनः पॉइंटर को आर वैल्यू के अंदर शून्य पर सेट करते हैं। चूंकि अस्थायी रूप से ये उपयोग नहीं किया जाएगा, कोई भी कोड अशक्त सूचक तक पहुंचने का प्रयास नहीं करेगा, और क्योंकि सूचक शून्य है, जब यह सीमा से बाहर हो जाता है तो इसकी मेमोरी को हटाया नहीं जाता है। इसलिए, ऑपरेशन न केवल एक गहरी प्रतिलिपि की कीमत चुकाता है, बल्कि सुरक्षित और अदृश्य रहता है। | ||
मानक लाइब्रेरी के बाहर किसी प्रकार का परिवर्तन करने की आवश्यकता के अतिरिक्त आर वैल्यू संदर्भ वर्तमान समय में कोड के प्रदर्शन द्वारा होने वाले लाभ को प्रदान कर सकता हैं। इस प्रकार लौटाने वाले फ़ंक्शन के दिए गए मान का प्रकार <code>std::vector<T></code> अस्थायी को स्पष्ट रूप से परिवर्तन करने की आवश्यकता नहीं है। इस प्रकार <code>std::vector<T> &&</code> मूव कंस्ट्रक्टर को काॅल करने के लिए किया जाता हैं, क्योंकि अस्थायी रूप से स्वचालित रूप से प्रतिद्वंद्विता माना जाता है। (चूंकि, यदि <code>std::vector<T></code> किसी सी ++ 03 संस्करण है जिसमें चालक कन्स्ट्रक्टर नहीं है, तो कॉपी कन्स्ट्रक्टर को साथ में काॅल करता है, इस प्रकार <code>const std::vector<T>&</code> ऐसी महत्वपूर्ण मेमोरी को आवंटन के कारण उत्पन्न होती हैं।) | मानक लाइब्रेरी के बाहर किसी प्रकार का परिवर्तन करने की आवश्यकता के अतिरिक्त आर वैल्यू संदर्भ वर्तमान समय में कोड के प्रदर्शन द्वारा होने वाले लाभ को प्रदान कर सकता हैं। इस प्रकार लौटाने वाले फ़ंक्शन के दिए गए मान का प्रकार <code>std::vector<T></code> अस्थायी को स्पष्ट रूप से परिवर्तन करने की आवश्यकता नहीं है। इस प्रकार <code>std::vector<T> &&</code> मूव कंस्ट्रक्टर को काॅल करने के लिए किया जाता हैं, क्योंकि अस्थायी रूप से स्वचालित रूप से प्रतिद्वंद्विता माना जाता है। (चूंकि, यदि <code>std::vector<T></code> किसी सी ++ 03 संस्करण है जिसमें चालक कन्स्ट्रक्टर नहीं है, तो कॉपी कन्स्ट्रक्टर को साथ में काॅल करता है, इस प्रकार <code>const std::vector<T>&</code> ऐसी महत्वपूर्ण मेमोरी को आवंटन के कारण उत्पन्न होती हैं।) | ||
| Line 127: | Line 127: | ||
Object scalar = {0.43f, 10}; //One Object, with first=0.43f and second=10 | Object scalar = {0.43f, 10}; //One Object, with first=0.43f and second=10 | ||
Object anArray[] = <nowiki>{{13.4f, 3}, {43.28f, 29}, {5.934f, 17}}</nowiki>; //An array of three Objects</blockquote>यह स्थैतिक सूचियों के लिए बहुत उपयोगी है, या किसी संरचना को कुछ मूल्य के लिए आरंभ करना है। सी ++ किसी ऑब्जेक्ट को प्रारंभ करने के लिए कन्स्ट्रक्टर भी प्रदान करता है, लेकिन वे अधिकांशतः प्रारंभिक सूची के रूप में सुविधाजनक नहीं होते हैं। चूंकि, सी ++ 03 प्रारंभिक-सूचियों को केवल उन संरचनाओं और | Object anArray[] = <nowiki>{{13.4f, 3}, {43.28f, 29}, {5.934f, 17}}</nowiki>; //An array of three Objects</blockquote>यह स्थैतिक सूचियों के लिए बहुत उपयोगी है, या किसी संरचना को कुछ मूल्य के लिए आरंभ करना है। सी ++ किसी ऑब्जेक्ट को प्रारंभ करने के लिए कन्स्ट्रक्टर भी प्रदान करता है, लेकिन वे अधिकांशतः प्रारंभिक सूची के रूप में सुविधाजनक नहीं होते हैं। चूंकि, सी ++ 03 प्रारंभिक-सूचियों को केवल उन संरचनाओं और class पर अनुमति देता है जो सरल पुराने डेटा (पीओडी) परिभाषा के अनुरूप हैं; सी ++ 11 प्रारंभकर्ता-सूचियों को बढ़ाता है, इसलिए इन्हें मानक कंटेनर समेत सभी वर्गों के लिए <code>std::vector</code> का उपयोग किया जा सकता है। | ||
C++11 अवधारणा को टेम्प्लेट से बांधता है, जिसे <code>std::initializer_list</code> कहा जाता है। यह कंस्ट्रक्टर्स और अन्य फ़ंक्शंस को इनिशियलाइज़र सूचियों को पैरामीटर के रूप में लेने की अनुमति देता है। उदाहरण के लिए: | C++11 अवधारणा को टेम्प्लेट से बांधता है, जिसे <code>std::initializer_list</code> कहा जाता है। यह कंस्ट्रक्टर्स और अन्य फ़ंक्शंस को इनिशियलाइज़र सूचियों को पैरामीटर के रूप में लेने की अनुमति देता है। उदाहरण के लिए: | ||
| Line 269: | Line 269: | ||
====वैकल्पिक फ़ंक्शन सिंटैक्स ==== | ====वैकल्पिक फ़ंक्शन सिंटैक्स ==== | ||
सी (प्रोग्रामिंग लैंग्वेज) फंक्शन डिक्लेरेशन सिंटैक्स सी लैंग्वेज के फीवैरियेबल सेट के लिए पूरी तरह से पर्याप्त था। चूंकि सी ++ सी से विकसित हुआ, इसने मूल सिंटैक्स रखा और जहां आवश्यक हो वहां इसे बढ़ाया भी गया हैं। चूंकि, जैसे-जैसे C++ अधिक जटिल होता गया, इसने कई सीमाओं को उजागर किया, विशेष रूप से टेम्पलेट फ़ंक्शन घोषणाओं के संबंध में इसे उपयोग करते गए हैं। उदाहरण के लिए, सी ++ 03 में यह अमान्य है:<blockquote>template<class Lhs, class Rhs> | |||
Ret adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} //Ret must be the type of lhs+rhs</blockquote> | |||
प्रारूप <code>Ret</code> जो भी प्रकार का जोड़ है, जिसके द्वारा <code>Lhs</code> और <code>Rhs</code> उत्पादन करते हैं। उपरोक्त C++11 की फंक्शन क्षमता के साथ भी <code>decltype</code> का भी उपयोग किया जाता हैं। जिसके लिए ऐसा नहीं हो सकता: | |||
template<class Lhs, class Rhs> | |||
decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} //Not valid C++11 | |||
यह सी ++ नहीं है क्योंकि <code>lhs</code> और <code>rhs</code> अभी तक परिभाषित नहीं किया गया है, वे तब तक पहचानकर्ता नहीं होंगे जब तक कि पार्सर ने बचे हुए फ़ंक्शन प्रोटोटाइप को पार्स नहीं करते हैं। | |||
इसके आसपास फंक्शन करने के लिए, सी ++ 11 ने अनुगामी-रिटर्न-प्रकार के साथ एक नया फ़ंक्शन डिक्लेरेशन सिंटैक्स प्रस्तुत किया जाता हैं:<ref>{{cite web |url=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1978.pdf |title=Decltype (revision 5) |access-date=2022-02-16 |archive-date=2022-02-14 |archive-url=https://web.archive.org/web/20220214133743/http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n1978.pdf |url-status=live }}</ref><blockquote>template<class Lhs, class Rhs> | |||
auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;} </blockquote>इस सिंटैक्स का उपयोग अधिक सांसारिक फंक्शन घोषणाओं और परिभाषाओं के लिए किया जा सकता है:<blockquote>struct SomeStruct | |||
{ | |||
auto func_name(int x, int y) -> int; | |||
}; | |||
auto SomeStruct::func_name(int x, int y) -> int | |||
{ | { | ||
return x + y; | |||
}</blockquote>इस स्थिति में "ऑटो" कीवर्ड का उपयोग सिंटैक्स का भाग है और सी ++ 11 में स्वचालित प्रकार की कमी नहीं करता है। चूंकि, C ++ 14 से प्रारंभ होकर, अनुगामी रिटर्न प्रकार को पूर्ण रूप से हटाया जा सकता है और कंपाइलर रिटर्न प्रकार को स्वचालित रूप से घटा देता हैं।<ref>{{cite web|url=http://en.cppreference.com/w/cpp/language/auto|title=auto specifier (since C++11) - cppreference.com|website=en.cppreference.com|access-date=2016-10-18|archive-date=2016-10-20|archive-url=https://web.archive.org/web/20161020050910/http://en.cppreference.com/w/cpp/language/auto|url-status=live}}</ref> | |||
==== वस्तु निर्माण में सुधार ==== | ==== वस्तु निर्माण में सुधार ==== | ||
सी ++ 03 में, class के रचनाकारों को उस वर्ग की प्रारंभिक सूची में अन्य कन्स्ट्रक्टरों को कॉल करने की अनुमति नहीं है। प्रत्येक कंस्ट्रक्टर को अपने सभी वर्ग सदस्यों का निर्माण स्वयं करना चाहिए या निम्नानुसार एक सामान्य सदस्य फ़ंक्शन को कॉल करना चाहिए: | सी ++ 03 में, class के रचनाकारों को उस वर्ग की प्रारंभिक सूची में अन्य कन्स्ट्रक्टरों को कॉल करने की अनुमति नहीं है। प्रत्येक कंस्ट्रक्टर को अपने सभी वर्ग सदस्यों का निर्माण स्वयं करना चाहिए या निम्नानुसार एक सामान्य सदस्य फ़ंक्शन को कॉल करना चाहिए: | ||
class SomeType | |||
{ | |||
public: | |||
SomeType(int new_number) | |||
{ | |||
Construct(new_number); | |||
} | |||
SomeType() | |||
{ | |||
Construct(42); | |||
} | |||
private: | |||
void Construct(int new_number) | |||
{ | |||
number = new_number; | |||
} | |||
int number; | |||
}; | |||
बेस क्लास के कंस्ट्रक्टर सीधे पैरेंट class के संपर्क में नहीं लाया जा सकता हैं, बेस क्लास कंस्ट्रक्टर उपयुक्त होने पर भी प्रत्येक पैरेंट क्लास को कंस्ट्रक्टर को लागू करना चाहिए। इन सदस्यों की घोषणा के स्थल पर class के गैर-निरंतर डेटा सदस्यों को प्रारंभ नहीं किया जा सकता है। इन्हें केवल कंस्ट्रक्टर में इनिशियलाइज़ किया जा सकता है। | |||
बेस क्लास के कंस्ट्रक्टर सीधे | |||
C++11 इन सभी समस्याओं का समाधान प्रदान करता है। | C++11 इन सभी समस्याओं का समाधान प्रदान करता है। | ||
सी ++ 11 कंस्ट्रक्टर्स को अन्य पीयर कंस्ट्रक्टर्स (जिसे [[प्रतिनिधिमंडल (प्रोग्रामिंग)]] कहा जाता है) को कॉल करने की अनुमति देता है। यह कंस्ट्रक्टरों को कम से कम जोड़े गए कोड के साथ दूसरे कंस्ट्रक्टर के व्यवहार का उपयोग करने की अनुमति देता है। डेलिगेशन का उपयोग अन्य भाषाओं में किया गया है, उदाहरण के लिए, [[जावा (प्रोग्रामिंग भाषा)]] और [[उद्देश्य सी]] | सी ++ 11 कंस्ट्रक्टर्स को अन्य पीयर कंस्ट्रक्टर्स (जिसे [[प्रतिनिधिमंडल (प्रोग्रामिंग)]] कहा जाता है) को कॉल करने की अनुमति देता है। यह कंस्ट्रक्टरों को कम से कम जोड़े गए कोड के साथ दूसरे कंस्ट्रक्टर के व्यवहार का उपयोग करने की अनुमति देता है। डेलिगेशन का उपयोग अन्य भाषाओं में किया गया है, उदाहरण के लिए, [[जावा (प्रोग्रामिंग भाषा)]] और [[उद्देश्य सी|स्टेटमेंट सी]] इत्यादि। | ||
यह सिंटैक्स इस प्रकार है: | यह सिंटैक्स इस प्रकार है:<blockquote>class SomeType | ||
{ | { | ||
int number; | |||
public: | |||
SomeType(int new_number) : number(new_number) {} | |||
SomeType() : SomeType(42) {} | |||
};</blockquote>ध्यान दें कि, इस स्थिति में इसके प्रभाव को से इसे प्राप्त किया जा सकता था, <code>new_number</code> डिफ़ॉल्ट पैरामीटर के रूप में प्रयोग किया जाता हैं। इसका सिंटैक्स इंटरफ़ेस के अतिरिक्त फंक्शन में डिफ़ॉल्ट मान (42) को व्यक्त करने की अनुमति देता है - लाइब्रेरी कोड के अनुरक्षकों के लिए उपरोक्त लाभ प्राप्त होता हैं क्योंकि फ़ंक्शन पैरामीटर के लिए डिफ़ॉल्ट मान कॉल साइट्स के लिए "बेक्ड इन" हैं, जबकि कन्स्ट्रक्टर प्रतिनिधिमंडल अनुमति देता है लाइब्रेरी का उपयोग करके कोड के पुनर्संकलन के बिना मूल्य को परिवर्तित किया जाना है। | |||
क्लास बेस क्लास | यह मुख्य चेतावनी के साथ आता है: सी ++ 03 किसी ऑब्जेक्ट को तब बनाया जाता है जब उसका कन्स्ट्रक्टर निष्पादित करना समाप्त कर देता है, लेकिन सी ++ 11 किसी भी कन्स्ट्रक्टर के निष्पादन को समाप्त करने के बाद निर्मित ऑब्जेक्ट पर विचार करता है। चूंकि कई कंस्ट्रक्टर्स को निष्पादित करने की अनुमति दी जाती हैं, इसका अर्थ है कि कि प्रत्येक डेलिगेटिंग कंस्ट्रक्टर अपने स्वयं के प्रकार के पूर्ण रूप से निर्मित ऑब्जेक्ट पर निष्पादित होते हैं। डिराइव्ड क्लास कंस्ट्रक्टर अपने बेस क्लास में सभी डेलिगेशन पूरा होने के बाद निष्पादित करते हैं। | ||
बेस-क्लास कंस्ट्रक्टर्स के लिए C ++ 11 ऐसी क्लास को निर्दिष्ट करने की अनुमति देता है जो बेस क्लास कंस्ट्रक्टर्स को इनहेरिट करता हैं। इस प्रकार, सी ++ 11 कंपाइलर इनहेरिटेंस करने के लिए कोड उत्पन्न करता हैं और पैरेंट क्लास को बेस क्लास में अग्रेषित करेगा। यह एक ऑल-ऑर-नथिंग फीवैरियेबल है: या तो उस बेस क्लास के सभी कंस्ट्रक्टर्स को फॉरवर्ड किया जाता है या उनमें से कोई भी नहीं है। साथ ही, एक इनहेरिटेड कंस्ट्रक्टर का नाम रिज़ॉल्यूशन (प्रोग्रामिंग लैंग्वेज) नाम मास्किंग होगा जिसके अनुसार यह पैरेंट वर्ग के कंस्ट्रक्टर के हस्ताक्षर से मेल खाता है, और कई इनहेरिटेंस के लिए प्रतिबंध सम्मिलित हैं: क्लास कंस्ट्रक्टर्स मल्टीपल इनहेरिटेंस नहीं हो सकते हैं। | |||
इसका प्रारूप इस प्रकार है: | |||
class BaseClass | |||
{ | { | ||
public: | |||
BaseClass(int value); | |||
}; | |||
class DerivedClass : public BaseClass | |||
{ | |||
public: | |||
using BaseClass::BaseClass; | |||
} | |||
सदस्य इनिशियलाइजेशन के लिए, C++11 इस सिंटैक्स की अनुमति देता है: | |||
class SomeClass | |||
{ | |||
public: | |||
SomeClass() {} | |||
explicit SomeClass(int new_value) : value(new_value) {} | |||
private: | |||
int value = 5; | |||
क्लास का कोई भी कंस्ट्रक्टर इनिशियलाइज़ होगा <code>value</code> 5 के साथ, यदि कंस्ट्रक्टर अपने स्वयं के | }; | ||
क्लास का कोई भी कंस्ट्रक्टर इनिशियलाइज़ होगा <code>value</code> 5 के साथ, यदि कंस्ट्रक्टर अपने स्वयं के इनिशियलाइजेशन को ओवरराइड नहीं करता है। तो उपरोक्त खाली कंस्ट्रक्टर इनिशियलाइज़ हो जाएगा <code>value</code> जैसा कि क्लास की परिभाषा बताती है, लेकिन एक इंट लेने वाला कंस्ट्रक्टर इसे दिए गए पैरामीटर के लिए इनिशियलाइज़ करता हैं। | |||
यह ऊपर दिखाए गए असाइनमेंट इनिशियलाइज़ेशन के अतिरिक्त कंस्ट्रक्टर या यूनिफ़ॉर्म इनिशियलाइज़ेशन का भी उपयोग कर सकता है। | यह ऊपर दिखाए गए असाइनमेंट इनिशियलाइज़ेशन के अतिरिक्त कंस्ट्रक्टर या यूनिफ़ॉर्म इनिशियलाइज़ेशन का भी उपयोग कर सकता है। | ||
==== स्पष्ट ओवरराइड और अंतिम ==== | ==== स्पष्ट ओवरराइड और अंतिम ==== | ||
सी ++ 03 में, गलती से एक नया वर्चुअल फ़ंक्शन बनाना संभव है, जब कोई बेस क्लास फ़ंक्शन को ओवरराइड करने का | सी ++ 03 में, गलती से एक नया वर्चुअल फ़ंक्शन बनाना संभव है, जब कोई बेस क्लास फ़ंक्शन को ओवरराइड करने का आशय रखते हैं। उदाहरण के लिए:<blockquote>struct Base | ||
{ | { | ||
virtual void some_func(float); | |||
}; | }; | ||
struct Derived : Base | |||
{ | { | ||
मान लीजिए <code>Derived::some_func</code> बेस क्लास संस्करण को बदलने का | virtual void some_func(int); | ||
};</blockquote>मान लीजिए <code>Derived::some_func</code> बेस क्लास संस्करण को बदलने का आशय है। लेकिन इसके अतिरिक्त, क्योंकि इसमें एक अलग प्रकार का हस्ताक्षर है, यह दूसरा वर्चुअल फ़ंक्शन बनाता है। यह एक सरल समस्या है, मुख्य रूप से जब कोई उपयोगकर्ता बेस क्लास को संशोधित करने जाता है। | |||
C++11 इस समस्या को हल करने के लिए सिंटैक्स प्रदान करता है। | C++11 इस समस्या को हल करने के लिए सिंटैक्स प्रदान करता है।<blockquote>struct Base | ||
{ | { | ||
virtual void some_func(float); | |||
}; | }; | ||
struct Derived : Base | |||
{ | |||
virtual void some_func(int) override; // ill-formed - doesn't override a base class method | |||
};</blockquote>विशेष पहचानकर्ता का अर्थ है कि संकलक यह देखने के लिए आधार वर्ग की जाँच करेगा कि क्या इस सटीक हस्ताक्षर के साथ कोई आभासी फंक्शन है। और अगर वहाँ नहीं है, तो संकलक त्रुटि का संकेत देगा। | |||
}; | |||
सी ++ 11 class से इसके चाइल्ड्स को रोकने या पैरेंट class में ओवरराइडिंग विधियों को रोकने की क्षमता भी जोड़ता है। यह विशेष पहचानकर्ता के साथ <code>final</code> किया जाता है उदाहरण के लिए: | |||
{ | struct Base1 final { }; | ||