मैं सी ++ में बाइनरी पेड़ बना रहा हूं, और नोड क्लास के अंदर स्मार्ट पॉइंटर्स का उपयोग करते समय मुझे कुछ समस्याएं हैं। सामान्य पॉइंटर्स का उपयोग करते समय, सब कुछ ठीक काम करता है, लेकिन स्मार्ट पॉइंटर्स के साथ यह काम नहीं कर रहा है। मुझे लगता है कि समस्या इस पंक्ति में सम्मिलित विधि में है:

    '''
    binaryNode* node = this; // This is working
    std::shared_ptr<binaryNode> node {this}; // This throws "double free or corruption" error
    std::shared_ptr<binaryNode> node = shared_from_this (); // This throws "bad weak ptr error", I am correctly inheriting from  enable_shared_from_this
    '''

मैं स्मार्ट पॉइंटर्स के साथ binaryNode* node = this; को कैसे दोहरा सकता हूं? मैंने public std::enable_shared_from_this<binaryNode> को सफलतापूर्वक उपयोग करने का भी प्रयास किया। आपकी सहायताके लिए धन्यवाद!

संपादित करें: मैं खुद को थोड़ा और बेहतर तरीके से समझाने की कोशिश करूंगा। यह एक बाइनरी सर्च ट्री का insert() फ़ंक्शन है, जो इस तरह दिखता है (यह .cpp फ़ाइल है):

'''
#include "binarynode.h"

binaryNode::binaryNode(int value){
    this->value = value;
    this->right = nullptr;
    this->left = nullptr;
}

void binaryNode::insert(int value){

binaryNode* node = this;
while(true){
    if(value > node->value){
        if(node->right != nullptr){
            node = node->right;
        }else{
            node->right = new binaryNode(value);
            break;
        }
    }else if(value < node->value){
        if(node->left != nullptr){
            node = node->left;
        }else{
            node->left = new binaryNode(value);
            break;
        }
    }else{
        return;
     }
  }

स्मार्ट पॉइंटर्स का उपयोग करके मैं इसे कैसे दोहरा सकता हूं?

संपादित करें 2: यह मेरी .h फ़ाइल है:

'''
#ifndef BINARYNODE_H
#define BINARYNODE_H

class binaryNode
{
public:
    int value;
    binaryNode(int value);
    binaryNode* right;
    binaryNode* left;
    void insert(int value);
};

#endif // BINARYNODE_H

और यह मुख्य फाइल है:

#include <iostream>
#include "binarynode.h"

using namespace std;

void printTree(binaryNode* node){
    if(node == nullptr) return;
    cout << node->value << endl;
    printTree(node->left);
    printTree(node->right);
}

int main(){
    binaryNode* bn = new binaryNode(9);
    bn->insert(4);
    bn->insert(20);
    bn->insert(1);
    bn->insert(6);
    bn->insert(15);
    bn->insert(170);
    printTree(bn);
    return 0;
}
0
carlos de la morena 18 अप्रैल 2021, 12:34

3 जवाब

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

आपको shared_ptr<> का उपयोग करने की आवश्यकता नहीं है।

वास्तव में स्मार्ट पॉइंटर ऑब्जेक्ट पर स्वामित्व को 'हल' करने के लिए यहां हैं, इस प्रकार जब किसी ऑब्जेक्ट का एक ही मालिक होता है, तो unique_ptr<> का उपयोग किया जाना चाहिए, और जब स्वामित्व साझा किया जाता है, तो साझा_ptr का उपयोग किया जाता है। आपकी स्थिति में, स्वामित्व स्पष्ट है, प्रत्येक नोड अपने बाएं और दाएं सदस्यों का स्वामित्व है, इस प्रकार unique_ptr का उपयोग किया जा सकता है।

ट्री ट्रैवर्सल समस्या के लिए, स्मार्ट पॉइंटर्स के साथ खिलवाड़ न करें क्योंकि आप किसी स्वामित्व का अनुरोध नहीं कर रहे हैं, लेकिन केवल मूल्यों को देख रहे हैं, इस प्रकार कच्चे पॉइंटर्स ठीक हैं।

तो आप इस तरह कुछ खत्म कर सकते हैं:

#include <memory>
#include <iostream>

struct binaryNode {
    binaryNode(int value) : value(value) {}
    void insert(int value);

    int value = 0;
    std::unique_ptr<binaryNode> right;
    std::unique_ptr<binaryNode> left;
};

void binaryNode::insert(int value){

    binaryNode* node = this;
    while(true){
        if(value > node->value){
            if(node->right != nullptr){
                node = node->right.get();
            }else{
                node->right = std::make_unique<binaryNode>(value);
                break;
            }
        }else if(value < node->value){
            if(node->left != nullptr){
                node = node->left.get();
            }else{
                node->left = std::make_unique<binaryNode>(value);
                break;
            }
        }else{
            return;
        }
    }
}

void printTree(const binaryNode &node){
    std::cout << node.value << std::endl;
    if (node.left)
        printTree(*node.left);
    if (node.right)
        printTree(*node.right);
}

int main(){
    auto bn = std::make_unique<binaryNode>(9);
    bn->insert(4);
    bn->insert(20);
    bn->insert(1);
    bn->insert(6);
    bn->insert(15);
    bn->insert(170);
    printTree(*bn);
    return 0;
}

आप देख सकते हैं कि प्रिंट को पॉइंटर लेने की आवश्यकता नहीं है, यह संदर्भ पर काम कर सकता है।

0
OznOg 18 अप्रैल 2021, 10:52
  1. आप एक ही कच्चे पॉइंटर को एक से अधिक बार साझा पॉइंटर में सीधे परिवर्तित नहीं कर सकते हैं, क्योंकि तब आपके पास कई मालिक होंगे जो एक-दूसरे के बारे में कुछ नहीं जानते हैं, प्रत्येक को लगता है कि ऑब्जेक्ट पर इसका पूरा नियंत्रण है। यही कारण है कि std::shared_ptr<binaryNode> node {this} आपको डबल-डिलीट देता है।
  2. आप shared_from_this का उपयोग तब तक नहीं कर सकते जब तक कि कम से कम एक साझा सूचक पहले से ही आपकी वस्तु की ओर इशारा न कर रहा हो। इसलिए std::shared_ptr<binaryNode> node = shared_from_this () काम नहीं करता।

यदि आप साझा पॉइंटर्स चाहते हैं, तो उन सभी को साझा करें। उदाहरण के लिए:

 // binaryNode* bn = new binaryNode(9); <-- nope!
 auto bn = std::make_shared<binaryNode>(9);

 // binaryNode* node = this; <-- nope!
 std::shared_ptr<binaryNode> node = shared_from_this();

हालांकि मैं यहां साझा पॉइंटर्स का उपयोग करने की अनुशंसा नहीं करता हूं। अद्वितीय संकेत अधिक उपयुक्त हैं।

0
n. 1.8e9-where's-my-share m. 18 अप्रैल 2021, 10:52

C++ वेक्टर का उपयोग पुनरावर्ती डेटा संरचना का समर्थन करने के लिए किया जा सकता है। यह बहुत आसान है कि स्मार्ट पीआरटी का उपयोग करें। मूल रूप से आपके नोड स्टोर वेक्टर बच्चों में सदस्य के रूप में।

#include <vector>

using std::vector;


struct Node {
    Node() = default;
    Node(const Node &) = delete;
    Node(Node &&) = default;

    vector<Node> children;
};

int main()
{
    Node root;
    root.children.push_back(Node());
    root.children.push_back(Node());
    root.children[0].children.push_back(Node());
}
0
jiayuehua 18 अप्रैल 2021, 12:24