मामूली मामला को छोड़कर जहां आप स्पष्ट रूप से लैम्ब्डा में उल्लेख नहीं किया गया है, वहां दो कोने के मामले हैं जहां कोई अंतर हो सकता है।
सबसे पहले, निहित कैप्चर आम तौर पर उन इकाइयों को कैप्चर नहीं करते हैं जो odr-used नहीं हैं (लेकिन इसके अपवाद के लिए अगला आइटम देखें)। यह अन्य बातों के अलावा, भी शामिल है, इस तरह के decltype
और sizeof
, उन लोगों के रूप में unevaluated ऑपरेंड और साथ ही कुछ const
और constexpr
स्थानीय चर में वर्णित बातें जब कुछ संदर्भों में इस्तेमाल किया (नियमों का पूरा सेट के लिए [basic.def.odr] से परामर्श):
void f(int){}
void f2(const int &) {}
void t() {
const int x = 8;
constexpr double y = 8;
const double z = 8;
auto g = []{ f(x); }; // OK
auto g1 = [=]{ f(x); }; // OK, does not capture x
// usually won't fire, though not guaranteed
static_assert(sizeof(g) == sizeof(g1), "!!");
auto g2 = []{ f(y); }; // OK
auto g3 = []{ f(z); }; // Error, must capture z
auto g4 = []{ f2(x); }; // Error, must capture x since it's odr-used
auto g5 = [=]{ f2(x); }; // OK, captures x
auto g6 = []{ f2(+x); }; // OK, doesn't odr-use x
auto g7 = []{ f2(y); }; // OK
}
यदि आप मैन्युअल रूप से कैप्चर सूची लिखते हैं, तो यह संभव है कि आप तकनीकी रूप से आवश्यकतानुसार अधिक कैप्चर करेंगे, क्योंकि नियमों का संचालन करने वाले नियमों को नियंत्रित करना बहुत जटिल है।
दूसरा, जेनेरिक लैम्बडास में अंतर्निहित कैप्चर एक निर्भर अभिव्यक्ति में उपयोग की जाने वाली चीजों को कैप्चर करेगा, भले ही वे अनिवार्य रूप से ओड-प्रयुक्त नहीं हैं, सैनिटी के लिए। an example from the standard उधार:
void f(int, const int (&)[2] = {}) { } // #1
void f(const int&, const int (&)[1]) { } // #2
void test() {
const int x = 17;
auto g2 = [=](auto a) {
int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK: is a dependent expression, so captures x
// Will actually odr-use x only if sizeof(a) == 1
};
}
हालांकि, अगर आप वास्तव में कुछ है कि हो सकता है या हो सकता है-नहीं-हो-ओडीआर से इस्तेमाल किया जब एक सामान्य लैम्ब्डा लेखन पर कब्जा करने की आवश्यकता नहीं है; आपको केवल इसे कैप्चर करने की आवश्यकता होती है यदि आप फ़ंक्शन कॉल ऑपरेटर की विशेषज्ञता को तुरंत चालू करते हैं जो ओडीआर-चीज का उपयोग करता है। और इसलिए यदि आप परिणामी जेनेरिक लैम्ब्डा को इस तरह से कभी भी कॉल नहीं करते हैं जो इस मुद्दे पर समस्या का उपयोग करेगा, तो निहित कैप्चर आपको आवश्यक न्यूनतम से अधिक कैप्चर कर सकता है। उदाहरण के लिए, इस अनुमति दी है:
void test() {
const int x = 17;
auto g3 = [](auto a) { // no capture
int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK for now
};
}
जब तक आप कुछ भी जिसका आकार 1 है साथ g3
फोन नहीं है: g3(0)
ठेठ सिस्टम पर ठीक है, g3('\0')
नहीं है।
यदि आलसी लैम्ब्डा पैडेंटिक लैम्ब्डा के समान चर को कैप्चर करने के समाप्त होता है, तो मुझे कोई कारण नहीं दिखता कि प्रदर्शन या यहां तक कि जेनरेट किए गए मशीन कोड अलग-अलग क्यों हो सकते हैं। – alain
आईडीके अगर मानक के लिए अनुमति है या नहीं, लेकिन मुझे लगता है कि कंपाइलर केवल आपके द्वारा उपयोग किए जाने वाले चर को कैप्चर करेगा। – NathanOliver
अंतर पूरी तरह से वाक्य रचनात्मक है, अर्थपूर्ण नहीं। दोनों lambdas एक ही काम करते हैं। –