क्या निम्नलिखित परिभाषाओं के बीच अंतर है?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
यदि नहीं, तो C ++ 11 में कौन सी शैली पसंद की जाती है?
क्या निम्नलिखित परिभाषाओं के बीच अंतर है?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
यदि नहीं, तो C ++ 11 में कौन सी शैली पसंद की जाती है?
जवाबों:
मेरा मानना है कि एक अंतर है। आइए उनका नाम बदलें ताकि हम उनके बारे में अधिक आसानी से बात कर सकें:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
दोनों PI1
और PI2
जिसका अर्थ है कि आप उन्हें संशोधित नहीं कर सकते लगातार कर रहे हैं। हालांकि केवल PI2
एक संकलन-समय स्थिर है। इसका संकलन समय पर किया जाएगा । PI1
संकलन समय या रन समय पर आरंभ किया जा सकता है। इसके अलावा, केवल PI2
एक संदर्भ में उपयोग किया जा सकता है जिसके लिए एक संकलन-समय की आवश्यकता होती है। उदाहरण के लिए:
constexpr double PI3 = PI1; // error
परंतु:
constexpr double PI3 = PI2; // ok
तथा:
static_assert(PI1 == 3.141592653589793, ""); // error
परंतु:
static_assert(PI2 == 3.141592653589793, ""); // ok
किसके अनुसार आपको उपयोग करना चाहिए? जो भी आपकी आवश्यकताओं को पूरा करता है उसका उपयोग करें। क्या आप यह सुनिश्चित करना चाहते हैं कि आपके पास एक संकलन समय स्थिर है जो संदर्भों में उपयोग किया जा सकता है जहां एक संकलन-समय स्थिरांक की आवश्यकता है? क्या आप इसे रन टाइम में किए गए कंपीटिशन के साथ शुरू करना चाहते हैं? आदि।
const int N = 10; char a[N];
काम करता है, और सरणी सीमाएँ संकलन-समय स्थिरांक होनी चाहिए।
PI1
एक सरणी में उपयोग के लिए एक संकलन-समय अभिन्न निरंतर में परिवर्तित करने देता है, लेकिन एक गैर-प्रकार के अभिन्न टेम्पलेट पैरामीटर के रूप में उपयोग करने के लिए नहीं। इसलिए PI1
अभिन्न प्रकार के संकलन-समय की परिवर्तनीयता मुझे थोड़ी हिट और याद आती है।
enum
प्रारंभकर्ता केवल दोनों के बीच उल्लेखनीय मतभेद हैं const
और constexpr
(और न के लिए काम करता है double
वैसे भी)।
1 / PI1
और 1 / PI2
अलग परिणाम दे सकते हैं। मुझे नहीं लगता कि इस उत्तर में सलाह के रूप में यह तकनीकी काफी महत्वपूर्ण है।
constexpr double PI3 = PI1;
मेरे लिए सही तरीके से काम करता है। (MSVS2013 CTP)। मैं क्या गलत कर रहा हूं?
यहां कोई अंतर नहीं है, लेकिन यह तब मायने रखता है जब आपके पास एक प्रकार है जिसमें एक कंस्ट्रक्टर है।
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
एक स्थिर है, लेकिन यह संकलन-समय पर आरंभ करने का वादा नहीं करता है। s1
चिह्नित किया गया है constexpr
, इसलिए यह एक स्थिर और है, क्योंकि S
निर्माणकर्ता भी चिह्नित है constexpr
, इसे संकलन-समय पर आरंभ किया जाएगा।
ज्यादातर यह तब मायने रखता है जब रनटाइम पर इनिशियलाइज़ेशन समय लेने वाला होता है और आप उस काम को कंपाइलर पर छोड़ना चाहते हैं, जहाँ यह समय लेने वाला भी होता है, लेकिन संकलित प्रोग्राम के निष्पादन समय को धीमा नहीं करता है।
constexpr
यह था कि निदान के लिए वस्तु का संकलन-समय गणना असंभव होना चाहिए। यह कम स्पष्ट है कि क्या एक निरंतर पैरामीटर की अपेक्षा करने वाले फ़ंक्शन को संकलन-समय पर निष्पादित किया जा सकता है const
या नहीं , पैरामीटर को घोषित किया constexpr
जाना constexpr int foo(S)
चाहिए : यानी, यदि मैं कॉल करता हूं, तो संकलन-समय पर निष्पादित किया जाएगा foo(s0)
?
foo(s0)
संकलन-समय पर निष्पादित किया जाएगा, लेकिन आप कभी नहीं जानते हैं: एक कंपाइलर को इस तरह के अनुकूलन करने की अनुमति है। निश्चित रूप से, न तो 4.7.2 और न ही constexpr a = foo(s0);
constexpr एक मान इंगित करता है जो संकलन के दौरान स्थिर और ज्ञात है।
const एक मूल्य को इंगित करता है जो केवल स्थिर है; संकलन के दौरान यह जानना अनिवार्य नहीं है।
int sz;
constexpr auto arraySize1 = sz; // error! sz's value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
ध्यान दें कि कॉन्स्टैक्स के रूप में कॉन्स्टेंट समान गारंटी नहीं देता है, क्योंकि कॉम्प्लेक्स ऑब्जेक्ट्स को संकलन के दौरान ज्ञात मूल्यों के साथ आरंभीकृत नहीं किया जाना चाहिए।
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation
सभी कॉन्स्टैक्स प्रॉप्स कॉन्सट हैं, लेकिन सभी कॉन्सटेप ऑब्जेक्ट्स कॉन्सटेक्स्ट नहीं हैं।
यदि आप चाहते हैं कि संकलक यह सुनिश्चित करें कि एक चर का एक मूल्य है जिसका उपयोग संकलन-समय स्थिरांक की आवश्यकता वाले संदर्भों में किया जा सकता है, तो इसके लिए पहुंचने का उपकरण संकुचित नहीं है।
एक कॉन्सटेक्स प्रतीकात्मक स्थिरांक को एक मूल्य दिया जाना चाहिए जो संकलन समय पर जाना जाता है। उदाहरण के लिए:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
उन मामलों को संभालने के लिए जहां "वैरिएबल" का मूल्य एक ऐसे मूल्य के साथ आरम्भ किया जाता है, जो संकलन समय पर ज्ञात नहीं है, लेकिन आरंभीकरण के बाद कभी नहीं बदलता है, C ++ निरंतर (एक कॉन्स्ट ) का दूसरा रूप प्रदान करता है । उदाहरण के लिए:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
ऐसे " कांस्टेबल चर" दो कारणों से बहुत सामान्य हैं:
संदर्भ: "प्रोग्रामिंग: सिद्धांत और अभ्यास सी ++ का उपयोग करके" स्ट्रॉस्ट्रुप द्वारा