उदाहरण के लिए:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

struct TreeNode {
    vector<TreeNode> children;
    string name;
};

int main() {
    TreeNode leafNode;
    leafNode.name="c";
    TreeNode middleNode;
    middleNode.name="b";
    middleNode.children.push_back(leafNode);
    TreeNode rootNode;
    rootNode.name="a";
    rootNode.children.push_back(middleNode);
    rootNode=rootNode.children[0];
    cout <<rootNode.name <<endl;
}

आउटपुट c, CLANG और GCC दोनों में। बेशक, मुझे उम्मीद है कि यह b आउटपुट करेगा। यहाँ क्या चल रहा है?

c++
1
FlatAssembler 18 सितंबर 2020, 10:39

2 जवाब

सबसे बढ़िया उत्तर

जैसा कि अन्य ने टिप्पणियों में बताया है, आपको वास्तव में डीबगर सेट अप करने का प्रयास करना चाहिए और पहले अपना कोड डीबग करना चाहिए। इस तरह आप प्रोग्रामिंग में बहुत कुछ सीखते हैं।

हालांकि, यदि आप डिबगिंग के अभ्यस्त नहीं हैं, तो संभवतः आपके लिए समस्या का पता लगाना कठिन होगा, क्योंकि विचाराधीन कोड कंपाइलर जेनरेट किया गया है।

आप सही कह रहे हैं कि कॉपी कंस्ट्रक्टर कमोबेश आपके डेटा को भ्रष्ट करता है। लेकिन यह कंपाइलर्स की गलती नहीं है। डिफ़ॉल्ट कॉपी कंस्ट्रक्टर संदर्भ द्वारा अपना तर्क लेता है और आप rootNode के सदस्य का संदर्भ rootNode के कॉपी कंस्ट्रक्टर को पास कर रहे हैं। तो असल में आप वस्तु को स्वयं के एक हिस्से से अधिलेखित कर रहे हैं।

असाइनमेंट या कॉपी के दौरान कमोबेश क्या होता है:

TreeNode(const TreeNode& other) {
  children = other.children;
  name = other.name;
}

इसलिए यदि आप इस ऑपरेशन को rootNode.children[0] पास करते हैं, तो इसे प्रभावी रूप से कम कर दिया जाएगा:

rootNode.children = rootNode.children[0].children; // copies the children of 'b' to 'a'
rootNode.name     = rootNode.children[0].name;     // children[0] now refers to the first 
                                                   // of 'b's children, so name will be 'c' !!

एक संभावित समाधान यह है कि पहले इसका उपयोग करके एक सच्ची प्रतिलिपि बनाई जाए:

rootNode = TreeNode{ rootNode.children[0] };

संकलक के आधार पर व्यवहार भिन्न हो सकता है। वीएस2019 में आपके उदाहरण की कोशिश करते समय मुझे एक खाली आउटपुट मिलता है।

2
Excelcius 18 सितंबर 2020, 11:32

आपको सेल्फ असाइनमेंट या सेल्फ कॉपी कंस्ट्रक्शन का इस्तेमाल नहीं करना चाहिए। आंशिक असाइनमेंट है rootNode=rootNode.children[0]; इस समस्या से बचने के लिए पॉइंटर्स का इस्तेमाल करना चाहिए

#include <iostream>
#include <vector>
#include <string>
#include <memory> // for std::shared_ptr

using namespace std;

struct TreeNode; // forward declaration

using TreeNodePtr = std::shared_ptr<TreeNode>;

struct TreeNode {
    vector<TreeNodePtr> children;
    string name;
};

int main() {
    auto leafNode = std::make_shared<TreeNode>();
    leafNode->name="c";
    auto middleNode = std::make_shared<TreeNode>();
    middleNode->name="b";
    middleNode->children.push_back(leafNode);
    auto rootNode = std::make_shared<TreeNode>();
    rootNode->name="a";
    rootNode->children.push_back(middleNode);
    rootNode=rootNode->children[0];
    cout <<rootNode->name <<endl;
}
1
sba 18 सितंबर 2020, 11:38