9

पर विचार करें नीचेVS2013 डिफ़ॉल्ट प्रारंभ बनाम मूल्य प्रारंभ

struct B 
{ 
    B() : member{}{}; 
    int member[10]; 
}; 

int main() 
{ 
    B b; 
} 

VS2013 संकलक कोड निम्न चेतावनी देता है:

चेतावनी C4351: नए व्यवहार: सरणी 'बी :: सदस्य' के तत्वों हो जाएगा डिफ़ॉल्ट प्रारंभ 1> test.vcxproj -> C: \ Users \ asaxena2 \ दस्तावेज \ दृश्य स्टूडियो 2013 \ परियोजनाओं \ परीक्षण \ डीबग \ test.exe

यह here

प्रलेखित है के साथ सी ++ 11, और 'डिफ़ॉल्ट प्रारंभ' की अवधारणा को लागू है, जिसका अर्थ है कि B.member के तत्वों आरंभ नहीं किया जा जाएगा।

लेकिन मेरा मानना ​​है कि member{} को मूल्य प्रारंभ करना चाहिए और डिफ़ॉल्ट प्रारंभिकता नहीं करना चाहिए। क्या वीएस2013 कंपाइलर टूटा हुआ है?

$ 8,5/6

प्रकार T की एक वस्तु डिफ़ॉल्ट आरंभ करने के लिए इसका मतलब है: - अगर T (संभवत: सीवी-योग्य) वर्ग प्रकार (धारा 9), T के लिए डिफ़ॉल्ट निर्माता कहा जाता है (और अगर T में कोई सुलभ डिफ़ॉल्ट कन्स्ट्रक्टर नहीं है तो प्रारंभिकता खराब है);
- यदि T एक सरणी प्रकार है, तो प्रत्येक तत्व डिफ़ॉल्ट-प्रारंभ होता है;
- अन्यथा, कोई प्रारंभिकता नहीं की जाती है।
यदि कोई प्रोग्राम const की ऑब्जेक्ट के डिफ़ॉल्ट प्रारंभ के लिए कॉल करता है - योग्य प्रकार T, T उपयोगकर्ता द्वारा प्रदान किए गए डिफ़ॉल्ट कन्स्ट्रक्टर के साथ एक क्लास प्रकार होगा।

$ 8.5.1

एक वस्तु या प्रकार T के संदर्भ की सूची-प्रारंभ इस प्रकार परिभाषित किया गया है:
- प्रारंभकर्ता सूची में कोई तत्व है और T एक डिफ़ॉल्ट के साथ एक कक्षा प्रकार है निर्माता, वस्तु मूल्य-प्रारंभिक है।
- अन्यथा, यदि T एक कुल है, कुल प्रारंभिक कार्य किया जाता है (8.5.1)।

यदि कुल में सदस्यों के मुकाबले सूची में कम प्रारंभकर्ता-खंड हैं, तो प्रत्येक सदस्य को स्पष्ट रूप से प्रारंभ नहीं किया गया है, जिसे प्रारंभिक प्रारंभकर्ता सूची (8.5.4) से प्रारंभ किया जाएगा। [उदाहरण:

struct S { int a; const char* b; int c; }; 
    S ss = { 1, "asdf" }; 

initializes 1 साथ ss.a, "asdf" साथ ss.b, और ss.c रूप int() की अभिव्यक्ति के मूल्य के साथ, कि है, 0अंत उदाहरण]

+0

यह एक अच्छा सवाल है, लेकिन "विजुअल स्टूडियो कंपाइलर व्यवहार" एक भयानक शीर्षक है। इसे और अधिक अर्थपूर्ण में बदलने पर विचार करें। उस ने कहा, क्या आपने संकलक के व्यवहार की पुष्टि की है? यह सिर्फ एक भ्रामक चेतावनी हो सकता है। – hvd

+0

@ एचवीडी: इसे बदल दिया। धन्यवाद – user3701522

उत्तर

7

यह एक गलत तरीके से शब्दों में चेतावनी संदेश प्रतीत हो रहा है (और मैं इसे पहली जगह में एक चेतावनी प्रिंट कर रहा है हैरान हूँ), लेकिन व्यवहार सही है। B::member मूल्य प्रारंभ किया जा रहा है, जो int की सरणी के लिए शून्य प्रारंभ में बदल जाता है।

#include <iostream> 

struct B 
{ 
    B() : member{}{}; 
    int member[10]; 
}; 

struct C 
{ 
    C() {}; 
    int member[10]; 
}; 

int main() 
{ 
    B b; 
    for(auto const& a : b.member) std::cout << a << ' '; 
    std::cout << std::endl; 

    C c; 
    for(auto const& a : c.member) std::cout << a << ' '; 
    std::cout << std::endl; 
} 

आप संकलन और में चलाते हैं डीबग मोड इस उत्पादन में परिणाम है: यह निम्न का उपयोग कर प्रदर्शन किया जा सकता

0 0 0 0 0 0 0 0 0 0 
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 

दूसरी पंक्ति में संख्या 0xCCCCCCCC हैं, डिबग पैटर्न वीसी ++ कंपाइलर डीबग मोड में मेमोरी भरता है। इस प्रकार B::member शून्य-प्रारंभिक हो रहा है, जबकि C::member के लिए कोई प्रारंभिकता नहीं की जाती है।

अस्वीकरण: मुझे पता है कि एक गैर-आरंभिकृत चर से पढ़ अपरिभाषित व्यवहार है, लेकिन यह सबसे अच्छा सबूत मैं के साथ आ सकता है।

+1

मैंने डिस्सेप्लोर की भी जांच की और मुझे सदस्य चर के आकार के बड़े मूल्यों के लिए मेमसेट करने के लिए कॉल दिखाई देता है। इसलिए, स्मृति को स्पष्ट करने के लिए एक स्पष्ट कॉल है जिसका अर्थ है कि यह मानक द्वारा आवश्यक शून्य प्रारंभिक है। N के छोटे मानों के लिए यह एक अलग तरीके से 0 को अनुकूलित और सेट कर रहा है (तत्व द्वारा तत्व) – user3701522

2

कंपाइलर चेतावनी गलत है; यह वास्तव में मानक द्वारा आवश्यक मूल्य-प्रारंभिक प्रदर्शन कर रहा है।

उदाहरण:

#include <iostream> 

struct B { 
    B() : member{}{}; 
    int member[10]; 
}; 

int main() { 
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
    B &b = *new (a) B; 
    std::cout << b.member[9]; // prints '0' 
} 
0

MSDN page का कहना है:

C4351 मतलब यह है कि आप अपने कोड आप नए व्यवहार है, जो की संभावना है चाहते हैं का निरीक्षण करना चाहिए ... क्योंकि सरणी था स्पष्ट रूप से कन्स्ट्रक्टर के सदस्य प्रारंभिक सूची में जोड़ा गया है, चेतावनी को अक्षम करने के लिए warning प्राग्मा का उपयोग करें। नए व्यवहार को उपयोगकर्ताओं के लिए ठीक होना चाहिए।

तो आपको पूरी फ़ाइल के लिए एक पंक्ति या #pragma warning (disable:4351) के लिए #pragma warning (suppress:4351) जोड़ना होगा।

संबंधित मुद्दे