क्या C ++ संरचना के सदस्य डिफ़ॉल्ट रूप से 0 से प्रारंभ होते हैं?


200

मेरे पास यह है struct:

struct Snapshot
{
    double x; 
    int y;
};

मैं चाहता हूं xऔर y0. मैं डिफ़ॉल्ट रूप से 0 करूंगा या मुझे करना होगा:

Snapshot s = {0,0};

संरचना को शून्य करने के अन्य तरीके क्या हैं?


एक std :: map <> का उपयोग करें और एक कुंजी मौजूद नहीं होने पर 0 वापस करें।
जॉनी

जवाबों:


263

यदि आप संरचना को प्रारंभ नहीं करते हैं तो वे अशक्त नहीं हैं।

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

दूसरा सभी सदस्यों को शून्य बना देगा, पहला उन्हें अनिर्दिष्ट मूल्यों पर छोड़ देगा। ध्यान दें कि यह पुनरावर्ती है:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

दूसरा p.s.{x,y}शून्य कर देगा । यदि आपने अपनी संरचना में कंस्ट्रक्टर प्राप्त किए हैं तो आप इन एग्रीगेट इनिशियलाइज़र सूचियों का उपयोग नहीं कर सकते। अगर ऐसा है, तो आपको उन कंस्ट्रक्टरों में उचित इनबिल्टेशन जोड़ना होगा

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

X और y दोनों को 0. को इनिशियलाइज़ करेगा। ध्यान दें कि आप x(), y()उन्हें उनके प्रकार की अवहेलना करने के लिए इनिशियलाइज़ करने के लिए उपयोग कर सकते हैं : यह तब वैल्यू इनिशियलाइज़ेशन है, और आमतौर पर एक उचित इनिशियल वैल्यू (0 के लिए इंटि, 0.0 डबल के लिए, डिफॉल्ट कंस्ट्रक्टर को यूज़र्स के लिए परिभाषित करता है) प्रकार जिनके पास उपयोगकर्ता घोषित निर्माता हैं, ...)। यह विशेष रूप से महत्वपूर्ण है अगर आपकी संरचना एक टेम्पलेट है।


1
यह मेरे संकलक में बहुत सारी चेतावनियाँ पैदा करता है।
रिवर-क्लेयर विलियमसन

1
रोजर: इनिशियलाइज़र में नामित संरचना का उपयोग करने का प्रयास करें, यही मैं करता हूं और मुझे वीसी 2012 में कोई चेतावनी नहीं मिलती है: स्नैपशॉट s = स्नैपशॉट ();
किट 10

@ जोहान्स स्काउब - litb Snapshot s = {};गैर POD सदस्यों के लिए काम करेगा (उन्हें शून्य करने के लिए)?
13:58

2
C ++ 11 अब आपको उन्हें संरचना या वर्ग की परिभाषा में आरंभ करने की अनुमति देता है, जैसे: संरचना स्नैपशॉट {डबल x {0}; // ब्रेसिज़ int y = 0 के साथ; // या सिर्फ पुरानी स्कूल शैली 'असाइनमेंट द्वारा' जो वास्तव में आरंभीकरण भी है};
.क्कु १००

1
"स्नैपशॉट s = {};" मानक का हिस्सा?
स्टीफन

40

नहीं, वे डिफ़ॉल्ट रूप से 0 नहीं हैं। यह सुनिश्चित करने का सबसे सरल तरीका है कि सभी मानों या डिफ़ॉल्ट 0 को एक कंस्ट्रक्टर को परिभाषित करना है

Snapshot() : x(0), y(0) {
}

यह सुनिश्चित करता है कि स्नैपशॉट के सभी उपयोगों में आरंभिक मूल्य होंगे।


24
नकारात्मक पक्ष यह है कि संरचना अब POD प्रकार नहीं है, क्योंकि इसमें एक कंस्ट्रक्टर है। यह कुछ संचालन को तोड़ देगा जैसे कि इसे एक अस्थायी फ़ाइल में लिखना।
फिन जुव

16
@finnw: C ++ 11 इसे ठीक करता है, हालांकि संरचना POD नहीं है, यह "मानक लेआउट" है।
बेन Voigt

19

सामान्य तौर पर, नहीं। हालाँकि, किसी फंक्शन में फाइल-स्कोप या स्टैटिक के रूप में घोषित एक संरचना / 0 के लिए इनिशियलाइज़ की जाएगी (ठीक उसी तरह जैसे कि सभी स्कोप के अन्य वैरिएबल):

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}

1
यह वास्तव में एक सुरक्षित धारणा नहीं है। आप किसी भी चीज के मूल्य पर भरोसा नहीं करना चाहिए जिसे आपने शुरू नहीं किया था
हस्तुरकुन

24
स्टैटिक स्टोरेज अवधि ऑब्जेक्ट्स को हमेशा शून्य से आरंभ किया जाता है - मानक से उद्धरण के लिए stackoverflow.com/questions/60653/… देखें । यह अच्छी शैली है या नहीं यह एक और मामला है।
बोल्डन

12

POD के साथ आप भी लिख सकते हैं

Snapshot s = {};

आपको C ++ में मेमसेट का उपयोग नहीं करना चाहिए, मेमसेट में यह खामी है कि यदि संरचना में गैर-पीओडी है तो वह इसे नष्ट कर देगा।

या इस तरह:

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();

@LightnessRacesinOrbit ओह वाट?
बेन सिनक्लेयर

@ एंडी मोस्ट वैक्सिंग पार्स उन चीजों को बदल देती है जो सामान्य सीटर की तरह दिखती हैं - SomeType foo();विशिष्ट है, हालांकि यह दूसरों के साथ हो सकता है - फ़ंक्शन परिभाषाओं में (उस मामले में, एक फ़ंक्शन fooजो वापस लौटता है SomeType)। नेक्रो के लिए खेद है, लेकिन अगर किसी और ने इस पार ठोकर खाई, तो मुझे लगा कि मैं जवाब दूंगा।
निधि मोनिका का मुकदमा

7

C ++ में, बिना तर्क वाले कंस्ट्रक्टर का उपयोग करें। सी में आपके पास कंस्ट्रक्टर नहीं हो सकते हैं, इसलिए या तो उपयोग करें memsetया - दिलचस्प समाधान - नामित शुरुआती।

struct Snapshot s = { .x = 0.0, .y = 0.0 };

मेरा मानना ​​है कि यह C है, C ++ नहीं है। यह कुछ C ++ कंपाइलर के तहत संकलन करने में विफल रहेगा। मैंने Cygwin या MinGW के तहत संकलन विफलता का अनुभव किया।
jww

3

मेरा मानना ​​है कि सही उत्तर यह है कि उनके मूल्य अपरिभाषित हैं। अक्सर, कोड के डिबग संस्करण चलाते समय उन्हें 0 से प्रारंभ किया जाता है। रिलीज़ संस्करण चलाते समय यह आमतौर पर ऐसा नहीं होता है।


2
वास्तव में डिबग संस्करण केवल 0उन जगहों पर पहले से ही स्मृति में होते हैं। यह आरंभीकरण के समान नहीं है!
को ऑर्बिट

3

चूँकि यह एक POD है (अनिवार्य रूप से C संरचना) इसे C को शुरू करने में थोड़ा नुकसान है:

Snapshot s;
memset(&s, 0, sizeof (s));

या इसी तरह

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

मैं calloc()एक सी ++ प्रोग्राम में उपयोग करने के लिए इतनी दूर नहीं जाऊंगा, हालांकि।


3
डबल के लिए समान है; सभी बिट्स शून्य जरूरी 0.0 नहीं है। हालाँकि, आप देख सकते हैं कि आपके पास IEEE754 डबल्स हैं, इस स्थिति में उसे काम करना होगा।
एमएसलटर्स

1

अपनी प्रारंभिक सूची को छोटा करने के लिए पॉड सदस्यों को एक बेस क्लास में ले जाएँ:

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.