केवल एक सदस्य के साथ एक संघ का उपयोग करने का उद्देश्य क्या है?


89

जब मैं seastar source code पढ़ रहा था , तो मैंने देखा कि एक संघ संरचना है जिसे tx_sideकेवल एक सदस्य कहा जाता है । क्या यह एक निश्चित समस्या से निपटने के लिए कुछ हैक है?

FYI करें, मैं tx_sideनीचे की संरचना चिपकाता हूं :

union tx_side {
    tx_side() {}
    ~tx_side() {}
    void init() { new (&a) aa; }
    struct aa {
        std::deque<work_item*> pending_fifo;
    } a;
} _tx;

1
के संभावित डुप्लिकेट stackoverflow.com/questions/26572432/...
मैक्स लैंगहॉफ

5
@MaxLanghof इस सवाल और इसी जवाब में इस तरह के संघ संरचना का उपयोग करने के उद्देश्य के बारे में उल्लेख नहीं किया गया था।
दाओलीकर

क्या आपके पास इस सदस्य के उपयोग के लिए एक उदाहरण है?
n314159

4
इसीलिए मैंने वास्तव में अपने बाइंडिंग क्लोज वोट का उपयोग नहीं किया। लेकिन मुझे यकीन नहीं है कि आप वास्तव में अपने प्रश्न के उत्तर से क्या उम्मीद करते हैं जो सीधे वहां के उत्तरों से पालन नहीं करता है। संभवतया unionइसके बजाय का उपयोग करने का उद्देश्य structदोनों के बीच एक या अधिक अंतर है। यह एक बहुत अस्पष्ट तकनीक है, जब तक कि उस कोड के मूल लेखक के साथ नहीं आता है मुझे यकीन नहीं है कि कोई व्यक्ति आपको एक आधिकारिक जवाब दे सकता है कि वे किस समस्या को हल करने की उम्मीद कर रहे हैं (यदि कोई हो)।
मैक्स लैंगहॉफ

2
मेरा सबसे अच्छा अनुमान यह है कि यूनियन का उपयोग या तो देरी से निर्माण के लिए किया जाता है (जो इस मामले में कुछ हद तक बेकार है) या लंबित_फिफो के विनाश (जो स्मृति रिसाव की ओर जाता है) को रोकता है। लेकिन उपयोग के उदाहरण के बिना कहना मुश्किल है।
कॉन्स्टेंटिन स्टुपनिक

जवाबों:


82

क्योंकि tx_sideएक संघ है, tx_side()स्वचालित रूप से प्रारंभ / निर्माण नहीं करता है a, और ~tx_side()स्वचालित रूप से इसे नष्ट नहीं करता है। यह एक ठीक कणों के जीवनकाल में नियंत्रण की अनुमति देता है aऔर pending_fifoकिसी प्लेसमेंट नए और मैनुअल नाशक कॉल (एक गरीब आदमी का माध्यम std::optional)।

यहाँ एक उदाहरण है:

#include <iostream>

struct A
{
    A() {std::cout << "A()\n";}
    ~A() {std::cout << "~A()\n";}
};

union B
{
    A a;
    B() {}
    ~B() {}
};

int main()
{
    B b;
}

यहाँ, B b;कुछ भी नहीं छापता है, क्योंकि aन तो निर्माण होता है और न ही विनाश होता है।

अगर Bएक था struct, B()कॉल करेगा A(), और ~B()कॉल करेगा ~A(), और आप इसे रोकने में सक्षम नहीं होंगे।


23
@daoliker जरूरी नहीं कि आप यादृच्छिक हों, लेकिन आपके द्वारा अप्रत्याशित। किसी भी अन्य असमान परिवर्तनशील चर के समान। आप इसे यादृच्छिक नहीं मान सकते हैं; आप सभी जानते हैं कि यह उपयोगकर्ता का पासवर्ड पकड़ सकता है जिसे आपने पहले टाइप करने के लिए कहा था।
user253751

5
@daoliker: पिछली टिप्पणी बहुत आशावादी है। रैंडम बाइट्स का मान 0-255 के बीच होता है, लेकिन यदि आप एक अनइंस्टाल्यूटेड बाइट को पढ़ते हैं तो आप intप्राप्त कर सकते हैं 0xCCCCCCCC। Uninitialized डेटा पढ़ना अनिर्धारित व्यवहार है, और क्या हो सकता है कि संकलक प्रयास को त्याग देता है। यह सिर्फ सिद्धांत नहीं है। डेबियन ने यह सटीक गलती की, और इसने उनके ओपनएसएसएल कार्यान्वयन को तोड़ दिया। उनके पास कुछ वास्तविक यादृच्छिक बाइट्स थे, एक असंगठित चर जोड़ा, और संकलक ने कहा "अच्छी तरह से परिणाम अपरिभाषित है, इसलिए यह शून्य हो सकता है"। शून्य स्पष्ट रूप से यादृच्छिक नहीं है।
MSALERS

1
@ मालिक: क्या आपके पास इस दावे का स्रोत है? क्योंकि जो मुझे मिल सकता है वह बताता है कि ऐसा नहीं हुआ है: यह संकलक नहीं था जिसने इसे हटा दिया, लेकिन डेवलपर्स। ईमानदारी से, अगर किसी भी संकलक लेखक ने ऐसा अविश्वसनीय रूप से बुरा निर्णय लिया तो मैं आश्चर्यचकित रहूंगा। (देखें stackoverflow.com/questions/45395435/… )
जैक एदले

5
@ जेकएडली: कौन सा सटीक दावा? आपके पास एक अच्छा लिंक है, लगता है मुझे कहानी उलटी पड़ गई। ओपनएसएसएल ने तर्क को गलत पाया, और एक असंगठित चर का इस तरह से उपयोग किया कि एक संकलक कानूनी रूप से किसी भी परिणाम को मान सके। डेबियन ने सही ढंग से देखा, लेकिन ठीक किया। जैसा कि "इस तरह के बुरे निर्णय लेने वाले कंपाइलर"; वे यह निर्णय नहीं लेते। अनिर्धारित व्यवहार बुरा निर्णय है। ऑप्टिमाइज़र को सही कोड पर चलाने के लिए डिज़ाइन किया गया है। उदाहरण के लिए जीसीसी सक्रिय रूप से कोई हस्ताक्षरित अतिप्रवाह नहीं मानता है। "कोई असमान डेटा नहीं" मान लेना समान रूप से उचित है; इसका उपयोग असंभव कोड पथ को खत्म करने के लिए किया जा सकता है।
एमएसलेटर

1
@JackAidley मैं इसी तरह के मुद्दों का सामना कर चुका हूं, जो @MSalters अपने कोड में उल्लेख करते हैं; मैंने गलती से मान लिया था कि एक असिंचित वैरिएबल खाली होगा, और बाद की != 0तुलना सही होने पर चकित हो गई थी । जब से मैंने यह सुनिश्चित करने के लिए कि मैं उस जाल में फिर से न गिरूँ, त्रुटियों के रूप में संकलित चर का इलाज करने के लिए संकलक झंडे जोड़ दिए हैं।
टॉम लिंट

0

सरल शब्दों में, जब तक कि एक सदस्यीय संघ स्पष्ट रूप से निर्दिष्ट / आरम्भित नहीं करता है, आवंटित स्मृति को प्रारंभ नहीं करता है। यह कार्यक्षमता std:: optionalc ++ 17 में प्राप्त की जा सकती है ।


2
यह एक भ्रामक जवाब है। केवल एक सदस्य वाले संघ का आकार सदस्य के समान होगा। इस मेमोरी को केवल तब तक इनिशियलाइज़ नहीं किया जाएगा जब तक कि सदस्य को इनिशियलाइज़ नहीं किया जाता है।
किरिल दिम्रेनको 15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.