मैं सी ++ सीखने पर काम कर रहा हूं और मैंने 3 कक्षाएं बनाई हैं: नोडएडिटर, नोड, नोडियो।

अनिवार्य रूप से संपादक में नोड्स का एक वेक्टर होता है, प्रत्येक नोड में NodeIO इंस्टेंस का एक वेक्टर होता है।

मैं चाहता हूं कि प्रत्येक वर्ग वहां "मालिक" का संदर्भ दे सके।

मूल रूप से NodeIO कंस्ट्रक्टर नोड से एक पॉइंटर लेता है, नोड एडिटर को पॉइंटर लेता है।

class NodeEditor {
    NodeEditor() {
        ...push_back(Node(this));
    }
}

class Node {
    NodeEditor* owner;
    Node(NodeEditor* _owner) : owner{ _owner } {
        ...push_back(NodeIO(this));
    }
}

class NodeIO {
    Node* owner;
    NodeIO(Node* _owner) : owner{ _owner } { }
}

इसके बाद मुझे बाद में _owner पॉइंटर्स का उपयोग करना होगा।

जब मैं अपने प्रोजेक्ट में इसका प्रयास करता हूं, तो पहले _owner पॉइंटर सही स्थान की ओर इशारा करता है, लेकिन एक बार जब मुझे इसे बाद में पुनर्प्राप्त करने की आवश्यकता होती है, तो वास्तविक वस्तु अब उस पॉइंटर स्थान पर मौजूद नहीं होती है।

इस प्रकार के लेआउट को काम करने देने के लिए मेरे पास क्या विकल्प हैं? और क्या इस स्थिति में पालन करने के लिए एक और अधिक अनुशंसित पैटर्न है।

0
Hex Crown 27 मई 2018, 00:43

3 जवाब

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

आपने कोई कॉपी कंस्ट्रक्टर नहीं दिखाया है। इसके द्वारा, मुझे लगता है कि आप कंपाइलर द्वारा प्रदान किए गए डिफ़ॉल्ट कॉपी कंस्ट्रक्टर पर भरोसा कर रहे हैं। यही आपकी समस्या का स्रोत है।

जब आप उपयोग करते हैं:

    ...push_back(Node(this));

NodeEditor में, आप Node(this) की एक प्रति संगृहीत कर रहे हैं। हालांकि, अगर Node और NodeIO ने कॉपी कंस्ट्रक्टर को ठीक से लागू नहीं किया है, तो NodeIO ऑब्जेक्ट में Node ऑब्जेक्ट std::vector की ओर इशारा करेगा। Node ऑब्जेक्ट जो मान्य नहीं है - अस्थायी Node ऑब्जेक्ट।


यहां एक नमूना कार्यक्रम है जो समस्या दिखाता है।

#include <iostream>
#include <vector>

struct Node;

struct NodeIO {
   Node* owner;
   NodeIO(Node* _owner) : owner{ _owner } { }
};

struct NodeEditor;

struct Node {
   NodeEditor* owner;
   Node(NodeEditor* _owner) : owner(_owner)
   {
      std::cout << (void*)this << std::endl;
      nodeIOList.push_back(NodeIO(this));
      nodeIOList.push_back(NodeIO(this));
   }

   std::vector<NodeIO> nodeIOList;
};

struct NodeEditor {
   NodeEditor()
   {
      nodeList.push_back(Node(this));
      nodeList.push_back(Node(this));
   }
   std::vector<Node> nodeList;
};

int main()
{
   NodeEditor editor;
   for ( auto& node : editor.nodeList )
   {
      std::cout << (void*)(&node) << std::endl;
      for (auto& nodeIO : node.nodeIOList )
      {
         std::cout << (void*)(nodeIO.owner) << std::endl;
      }
   }
}

आउटपुट:

0x7ffe53d34c30
0x7ffe53d34c50
0xae10c0
0x7ffe1af7a2a0
0x7ffe1af7a2a0
0xae10e0
0x7ffe1af7a2c0
0x7ffe1af7a2c0

आउटपुट स्पष्ट रूप से Node ऑब्जेक्ट्स को पॉइंटर्स के मान दिखाता है जो Node(this) का उपयोग करके बनाए गए थे और पॉइंटर्स के मान Node ऑब्जेक्ट्स जो std::vector<Node> में स्टोर हैं। . कृपया ध्यान दें कि NodeIO ऑब्जेक्ट अभी भी अस्थायी Node ऑब्जेक्ट की ओर इशारा करते हैं। वे main में लटकने वाले सूचक हैं।


मैंने एक त्वरित सुधार की कोशिश की लेकिन यह काम नहीं किया। मुझे उस पर थोड़ा और काम करने की जरूरत है।


यहां एक समाधान है जो डिफ़ॉल्ट कॉपी कंस्ट्रक्टर्स के साथ काम करता है। यह वस्तुओं के std::vector के बजाय std::shared_ptr के std::vector का उपयोग करता है।

#include <iostream>
#include <vector>
#include <memory>

struct Node;

struct NodeIO {
   Node* owner;
   NodeIO(Node* _owner) : owner{ _owner } { }
};

struct NodeEditor;

struct Node {
   NodeEditor* owner;
   Node(NodeEditor* _owner) : owner(_owner)
   {
      std::cout << (void*)this << std::endl;
      nodeIOList.push_back(std::make_shared<NodeIO>(this));
      nodeIOList.push_back(std::make_shared<NodeIO>(this));
   }

   std::vector<std::shared_ptr<NodeIO>> nodeIOList;
};

struct NodeEditor {
   NodeEditor()
   {
      nodeList.push_back(std::make_shared<Node>(this));
      nodeList.push_back(std::make_shared<Node>(this));
   }
   std::vector<std::shared_ptr<Node>> nodeList;
};

int main()
{
   NodeEditor editor;
   for ( auto& node : editor.nodeList )
   {
      std::cout << (void*)(node.get()) << std::endl;
      for (auto& nodeIO : node->nodeIOList )
      {
         std::cout << (void*)(nodeIO.get()->owner) << std::endl;
      }
   }
}

आउटपुट:

0x1460c30
0x1461110
0x1460c30
0x1460c30
0x1460c30
0x1461110
0x1461110
0x1461110
1
R Sahu 27 मई 2018, 02:01

जब आप किसी सदिश में चीज़ें जोड़ते हैं, तो यह संभव है कि सभी सदिश के अवयव गतिमान हों। इस प्रकार, जब आप एक Node जोड़ते हैं, तो यह संभव है कि सभी मौजूदा NodeIO के स्वामी सूचक अमान्य हों।

इसे संभालने के लिए, आपको या तो

  • किसी भिन्न डेटा संरचना का उपयोग करें और Node की प्रतिलिपि को अक्षम करें और कंस्ट्रक्टरों को स्थानांतरित करें, या
  • Node के मूव कंस्ट्रक्टर के दौरान, इसमें शामिल सभी NodeIO के owner पॉइंटर्स को अपडेट करें, और सुनिश्चित करें कि यदि आप NodeIO को कॉल करते हैं तो नए NodeIO सही तरीके से बनाए गए हैं। Node कॉपी कंस्ट्रक्टर।

आप NodeEditors को कैसे स्टोर करते हैं, इस पर निर्भर करते हुए, आपको शायद उनके साथ भी ऐसा ही करना चाहिए।

1
Daniel H 27 मई 2018, 01:14

NodeEditor ऑब्जेक्ट और Node ऑब्जेक्ट और NodeIo ऑब्जेक्ट के जीवनकाल की जाँच करें। डायनामिक ऑब्जेक्ट बनाने के लिए नए ऑपरेटर का उपयोग करें, या सुनिश्चित करें कि NodeEditor और Node और NodeIo का आपका इंस्टेंटेशन एक ही दायरे में होता है। जांचें कि क्या आप NodeEditor ऑब्जेक्ट के Node कंटेनर की एक प्रति रखते हैं और NodeEditor ऑब्जेक्ट को जारी करने के बाद आप इसका उपयोग करते हैं।

0
Ali Asadpoor 27 मई 2018, 01:07