का उद्देश्य क्या है std::make_pair?
सिर्फ क्यों नहीं std::pair<int, char>(0, 'a')?
क्या दोनों विधियों में कोई अंतर है?
std::make_pairबेमानी है। इस विवरण के नीचे एक उत्तर है।
का उद्देश्य क्या है std::make_pair?
सिर्फ क्यों नहीं std::pair<int, char>(0, 'a')?
क्या दोनों विधियों में कोई अंतर है?
std::make_pairबेमानी है। इस विवरण के नीचे एक उत्तर है।
जवाबों:
अंतर यह है कि std::pairआपको दोनों तत्वों के प्रकारों को निर्दिष्ट करने की आवश्यकता है, जबकि std::make_pairउन तत्वों के प्रकार के साथ एक जोड़ी बनाई जाएगी जो इसे पारित किए बिना, आपको यह बताने की आवश्यकता नहीं है। यही कारण है कि मैं विभिन्न डॉक्स वैसे भी इकट्ठा कर सकता हूं।
इस उदाहरण को http://www.cplusplus.com/reference/std/utility/make_pair/ से देखें
pair <int,int> one;
pair <int,int> two;
one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>
इसके निहितार्थ बोनस के अलावा, यदि आपने मेकप का उपयोग नहीं किया है तो आपको करना होगा
one = pair<int,int>(10,20)
हर बार जब आप एक को सौंपा, जो समय के साथ कष्टप्रद होगा ...
std::make_pair। जाहिर है यह सिर्फ सुविधा के लिए है।
one = {10, 20}आजकल कर सकते हैं लेकिन मेरे पास इसे जांचने के लिए C ++ 11 संकलक काम नहीं है।
make_pairसंरचना, यूनियनों, लंबदा और अन्य डूडोड सहित अनाम प्रकारों के साथ काम करता है।
जैसा कि @MSalters ने उत्तर दिया है, अब आप C ++ 11 में ऐसा करने के लिए घुंघराले ब्रेसिज़ का उपयोग कर सकते हैं (बस इसे C ++ 11 संकलक के साथ सत्यापित करें):
pair<int, int> p = {1, 2};
क्लास टेम्पलेट तर्क सी ++ 17 से पहले कंस्ट्रक्टर से अनुमान नहीं लगाया जा सकता है
C ++ 17 से पहले आप कुछ ऐसा नहीं लिख सकते थे:
std::pair p(1, 'a');
चूंकि वह कंस्ट्रक्टर के तर्कों से टेम्पलेट प्रकारों का अनुमान लगाएगा।
C ++ 17 उस वाक्यविन्यास को संभव बनाता है, और इसलिए make_pairनिरर्थक है।
C ++ 17 से पहले, std::make_pairहमें कम क्रिया कोड लिखने की अनुमति दी:
MyLongClassName1 o1;
MyLongClassName2 o2;
auto p = std::make_pair(o1, o2);
अधिक क्रिया के बजाय:
std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};
जो प्रकारों को दोहराता है, और बहुत लंबा हो सकता है।
उस पूर्व-सी ++ 17 केस में टाइप इंफ़ेक्शन काम करता है क्योंकि make_pairकंस्ट्रक्टर नहीं है।
make_pair अनिवार्य रूप से इसके बराबर है:
template<class T1, class T2>
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) {
return std::pair<T1, T2>(t1, t2);
}
एक ही अवधारणा inserterबनाम पर लागू होती है insert_iterator।
यह सभी देखें:
न्यूनतम उदाहरण
चीजों को अधिक ठोस बनाने के लिए, हम समस्या को न्यूनतम रूप से देख सकते हैं:
main.cpp
template <class MyType>
struct MyClass {
MyType i;
MyClass(MyType i) : i(i) {}
};
template<class MyType>
MyClass<MyType> make_my_class(MyType i) {
return MyClass<MyType>(i);
}
int main() {
MyClass<int> my_class(1);
}
फिर:
g++-8 -Wall -Wextra -Wpedantic -std=c++17 main.cpp
खुशी से संकलित करता है, लेकिन:
g++-8 -Wall -Wextra -Wpedantic -std=c++14 main.cpp
के साथ विफल रहता है:
main.cpp: In function ‘int main()’:
main.cpp:13:13: error: missing template arguments before ‘my_class’
MyClass my_class(1);
^~~~~~~~
और काम करने के बजाय आवश्यकता होती है:
MyClass<int> my_class(1);
या सहायक:
auto my_class = make_my_class(1);
जो एक कंस्ट्रक्टर के बजाय एक नियमित फ़ंक्शन का उपयोग करता है।
`Std :: reference_wrapper के लिए अंतर
इस टिप्पणी को कहा गया है कि std::make_pairunwraps std::reference_wrapper, जबकि निर्माता नहीं करता है, तो यह है कि एक अंतर है। TODO उदाहरण।
जीसीसी 8.1.0, उबंटू 16.04 के साथ परीक्षण किया गया ।
std::make_pairC ++ 17 में पदावनत नहीं किया गया?
make_pair संदर्भ आवरणों को हटाता है, इसलिए यह वास्तव में CTAD से अलग है।
उपयोग करने के बीच कोई अंतर नहीं है make_pairpairनिर्दिष्ट प्रकार के तर्कों के साथ कंस्ट्रक्टर को और स्पष्ट रूप से कॉल करने के है। std::make_pairप्रकार सुविधाजनक होता है जब प्रकार क्रिया होते हैं क्योंकि एक टेम्पलेट विधि में दिए गए मापदंडों के आधार पर प्रकार में कटौती होती है। उदाहरण के लिए,
std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair;
std::vector<int> emptyV;
// shorter
vecOfPair.push_back(std::make_pair(emptyV, emptyV));
// longer
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV));
यह ध्यान देने योग्य है कि यह C ++ टेम्पलेट प्रोग्रामिंग में एक सामान्य मुहावरा है। यह ऑब्जेक्ट जनरेटर मुहावरे के रूप में जाना जाता है, आप अधिक जानकारी और एक अच्छा उदाहरण यहां पा सकते हैं ।
संपादित करें जैसा कि किसी ने टिप्पणियों में सुझाया है (हटाए जाने के बाद) यह टूटने की स्थिति में लिंक से थोड़ा संशोधित उद्धरण है।
ऑब्जेक्ट जेनरेटर उनके प्रकारों को स्पष्ट रूप से निर्दिष्ट किए बिना वस्तुओं के निर्माण की अनुमति देता है। यह फ़ंक्शन टेम्प्लेट्स की एक उपयोगी संपत्ति पर आधारित है, जो क्लास टेम्प्लेट नहीं है: किसी फ़ंक्शन टेम्प्लेट के प्रकार अपने वास्तविक मापदंडों से स्वचालित रूप से काटे जाते हैं। std::make_pairएक सरल उदाहरण है जो फ़ंक्शन std::pairके वास्तविक मापदंडों के आधार पर टेम्पलेट का एक उदाहरण देता std::make_pairहै।
template <class T, class U>
std::pair <T, U>
make_pair(T t, U u)
{
return std::pair <T, U> (t,u);
}
&&में C ++ 11 के बाद से।
make_pair डायरेक्ट कंस्ट्रक्टर पर एक अतिरिक्त कॉपी बनाता है। मैं हमेशा अपने जोड़े को सरल वाक्य रचना प्रदान करने के लिए टाइप करता हूं।
यह अंतर दिखाता है (रामपाल चौधरी द्वारा उदाहरण):
class Sample
{
static int _noOfObjects;
int _objectNo;
public:
Sample() :
_objectNo( _noOfObjects++ )
{
std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
}
Sample( const Sample& sample) :
_objectNo( _noOfObjects++ )
{
std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
}
~Sample()
{
std::cout<<"Destroying object "<<_objectNo<<std::endl;
}
};
int Sample::_noOfObjects = 0;
int main(int argc, char* argv[])
{
Sample sample;
std::map<int,Sample> map;
map.insert( std::make_pair( 1, sample) );
//map.insert( std::pair<int,Sample>( 1, sample) );
return 0;
}
std::moveसिर्फ अंदर insertऔर / या उसके आस-पास वही परिणाम मिलते हैं जो एक संदर्भ होगा sample। यह केवल तब होता है जब मैं बदलने std::map<int,Sample>के लिए std::map<int,Sample const&>है कि मैं का निर्माण वस्तुओं की संख्या को कम, और केवल जब मैं प्रतिलिपि निर्माता है कि मैं सभी प्रतियों (जाहिर है) को खत्म करने को हटा दें। उन दोनों परिवर्तनों को करने के बाद, मेरे परिणाम में डिफ़ॉल्ट निर्माता के लिए एक कॉल और एक ही ऑब्जेक्ट के लिए विध्वंसक को दो कॉल शामिल हैं। मुझे लगता है कि मुझे कुछ याद आ रहा होगा। (जी ++ 5.4.1, सी ++ 11)
emplaceबजाय सिफारिश करूंगा कि insertयदि आप तुरंत सम्मिलित करने के लिए एक मान का निर्माण कर रहे हैं (और आप अतिरिक्त उदाहरण नहीं चाहते हैं।) यह मेरी विशेषज्ञता का क्षेत्र नहीं है, अगर मैं कह सकता हूं कि मेरे पास एक है, लेकिन प्रतिलिपि / चाल C ++ 11 द्वारा शुरू किए गए शब्दार्थ ने मुझे बहुत मदद की है।
c ++ 11 से शुरू होकर जोड़े के लिए सिर्फ यूनिफॉर्म इनिशियलाइज़ेशन का उपयोग करें इसलिए इसके बजाय:
std::make_pair(1, 2);
या
std::pair<int, int>(1, 2);
महज प्रयोग करें
{1, 2};
{1, 2}एक जोड़ी को इनिशियलाइज़ करने के लिए इस्तेमाल किया जा सकता है, लेकिन टाइप पेयर के लिए प्रतिबद्ध नहीं है। यानी ऑटो का उपयोग करते समय आपको आरएचएस पर एक प्रकार के लिए प्रतिबद्ध होना चाहिए auto p = std::pair{"Tokyo"s, 9.00};:।