मुझे नहीं लगता कि कोई भी उत्तर वास्तव में यह स्पष्ट करता है कि इसके क्या दुष्प्रभाव हैं, या वास्तव में, यह क्या है।
constexprऔर constनाम-स्थान / फ़ाइल-स्कोप समान है जब एक शाब्दिक या अभिव्यक्ति के साथ आरंभ किया जाता है; लेकिन एक फ़ंक्शन के साथ, constकिसी भी फ़ंक्शन द्वारा आरंभीकृत किया जा सकता है, लेकिन constexprएक गैर-कॉन्स्ट्रेक्प (एक फ़ंक्शन जिसे कॉन्स्टैक्स या एक गैर कॉन्स्ट्रेक्स अभिव्यक्ति के साथ चिह्नित नहीं किया गया है) द्वारा संकलित किया जाता है। दोनों constexprऔर constचर के लिए परोक्ष आंतरिक संबंध हैं (अच्छी तरह से वास्तव में, वे अगर -O1 और मजबूत संकलन जोड़ने चरण के लिए प्राप्त करने के लिए जीवित नहीं है, और staticके लिए एक आंतरिक (स्थानीय) लिंकर प्रतीक फेंकना संकलक मजबूर नहीं करता है constया constexprजब पर -O1 या मजबूत, केवल समय यह ऐसा करता है, तो आप चर का पता लेते हैं। constऔर constexprजब तक साथ व्यक्त एक आंतरिक प्रतीक हो जाएगा externयानीextern constexpr/const int i = 3;उपयोग करने की आवश्यकता है)। एक समारोह को constexprबनाता समारोह स्थायी रूप से जोड़ने के स्तर तक पहुंच कभी नहीं (की परवाह किए बिना externया inlineपरिभाषा या -O0 या -Ofast में), जबकि constकभी नहीं करता है, और staticऔर inlineकेवल -O1 और इसके बाद के संस्करण पर इस प्रभाव है। जब किसी फ़ंक्शन द्वारा const/ constexprवैरिएबल को इनिशियलाइज़ किया जाता है constexpr, तो लोड को हमेशा किसी ऑप्टिमाइज़ेशन फ़्लैग के साथ ऑप्टिमाइज़ किया जाता है, लेकिन यह कभी भी ऑप्टिमाइज़ नहीं किया जाता है यदि फ़ंक्शन केवल staticया है inline, या यदि वैरिएबल ए const/ नहीं है constexpr।
मानक संकलन (-ओ 0)
#include<iostream>
constexpr int multiply (int x, int y)
{
return x * y;
}
extern const int val = multiply(10,10);
int main () {
std::cout << val;
}
के लिए संकलित करता है
val:
.long 100 //extra external definition supplied due to extern
main:
push rbp
mov rbp, rsp
mov esi, 100 //substituted in as an immediate
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
.
.
.
तथापि
#include<iostream>
const int multiply (int x, int y)
{
return x * y;
}
const int val = multiply(10,10); //constexpr is an error
int main () {
std::cout << val;
}
को संकलित करता है
multiply(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-4]
imul eax, DWORD PTR [rbp-8]
pop rbp
ret
main:
push rbp
mov rbp, rsp
mov eax, DWORD PTR val[rip]
mov esi, eax
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
.
.
.
mov esi, 10
mov edi, 10
call multiply(int, int)
mov DWORD PTR val[rip], eax
यह स्पष्ट रूप से पता चलता है कि constexprकी initialisation का कारण बनता है const/constexprफ़ाइल-गुंजाइश चर संकलन समय पर पाए जाते हैं और कोई वैश्विक चिह्न देने में है, जबकि का उपयोग नहीं यह पहले होने की initialisation का कारण बनता है mainरनटाइम पर।
संकलन का उपयोग कर -OIFT
यहां तक कि -Oxt लोड का अनुकूलन नहीं करता है! https://godbolt.org/z/r-mhif , इसलिए आपको चाहिए constexpr
constexprconstexprसमान परिणाम के लिए कार्यों को अन्य कार्यों के अंदर से भी बुलाया जा सकता है । constexprएक समारोह में भी कुछ भी है कि समारोह में संकलन समय पर नहीं किया जा सकता के उपयोग को रोकता है; उदाहरण के लिए, <<ऑपरेटर को कॉल करना std::cout।
constexprब्लॉक स्कोप में उसी तरह का व्यवहार किया जाता है, अगर वह एक गैर-कॉन्स्ट्रेक्स फ़ंक्शन द्वारा आरंभीकृत किया जाता है; मूल्य भी तुरंत प्रतिस्थापित किया जाता है।
अंत में, इसका मुख्य उद्देश्य सी के इनलाइन फ़ंक्शन की तरह है, लेकिन यह केवल तभी प्रभावी होता है जब फ़ंक्शन का उपयोग फ़ाइल-स्कोप वैरिएबल को इनिशियलाइज़ करने के लिए किया जाता है (जो फ़ंक्शंस C पर नहीं कर सकते, लेकिन वे C ++ पर कर सकते हैं क्योंकि यह फ़ाइल के डायनामिक इनिशियलाइज़ेशन की अनुमति देता है) स्कोप वैरिएबल), फ़ंक्शन को छोड़कर लिंकर के लिए एक वैश्विक / स्थानीय प्रतीक निर्यात नहीं कर सकता है, यहां तक कि उपयोग करना extern/static, जिसे आप inlineसी पर कर सकते हैं ; ब्लॉक-स्कोप वैरिएबल असाइनमेंट फ़ंक्शंस constexprको C और C ++ के बिना -O1 ऑप्टिमाइज़ेशन का उपयोग करके केवल इनलाइन किया जा सकता है ।
constexprएक संकलन-समय स्थिर बनाता है;constबस इसका मतलब है कि मूल्य नहीं बदला जा सकता है।