簡體   English   中英

如何正確使用 class 內部的智能指針

[英]How to correctly use smart pointers inside of a class

我在 C++ 中創建二叉樹,在節點 class 內部使用智能指針時遇到一些問題。 使用普通指針時,一切正常,但使用智能指針時,它就無法正常工作。 我認為問題出在插入方法中的這一行:

    '''
    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() function,如下所示(這是 .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:這是 my.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;
}
  1. 您不能多次將相同的原始指針直接轉換為共享指針,因為這樣您將有幾個彼此一無所知的所有者,每個所有者都認為它可以完全控制 object。 這就是為什么std::shared_ptr<binaryNode> node {this}給你一個雙重刪除。
  2. 你也不能使用shared_from_this除非至少有一個共享指針已經指向你的 object。 這就是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();

我不建議在這里使用共享指針。 唯一指針更合適。

您不需要使用 shared_ptr<>。

實際上,智能指針在這里“解決” object 的所有權,因此當 object 有一個所有者時,應該使用 unique_ptr<>,當所有權共享時,使用 shared_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;
}

您可能會注意到 print 不需要使用指針,它可以在引用上工作。

C++ 向量可用於支持遞歸數據結構。 使用 smart ptr 要簡單得多。 基本上在您的節點中存儲向量子項作為成員。

#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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM