如何使用智能指针构建树

how to use smart pointer to build a tree?

本文关键字:构建 指针 智能 何使用      更新时间:2023-10-16

假设我有一个员工树,每个员工都有同事,同事也有同事。。。。。我设置了两个类employee,用于存储员工的信息,eTree表示体系结构。

每个员工都有一个指向同事的矢量存储智能指针。查看以下代码。为什么智能指针指向的地址最终变为00000000。我已经返回了函数buildChilds的指针。

#include <iostream>
#include <string>
#include <vector>
#include <memory>
class employee
{
    std::string NAME;
    int NUM;
    int Enum = 0;
public:
    std::vector<std::shared_ptr<employee>> childs;
    employee(std::string name, int num) :NAME(name), NUM(num)
    {
        childs.resize(num);
    }
    std::string getName()
    {
        return NAME;
    }
    int getNum()
    {
        return NUM;
    }
    void setEnum(int num)
    {
        Enum = num;
    }
    int getEnum()
    {
        return Enum;
    }
};
class eTree
{
private:
    std::shared_ptr<employee> proot;
public:
    eTree(employee node) { proot = std::make_shared<employee> (node); }
    void buildTree(std::shared_ptr<employee> parent);
    std::shared_ptr<employee> getP() { return proot; }
    std::shared_ptr<employee> buildChilds(employee &parent, int i);
};
void eTree::buildTree(std::shared_ptr<employee> parent)
{
    int num = parent->getNum();
    if (num != 0)
    {
        for (int i = 0; i < num; i++)
        {
            (*parent).childs[i] = buildChilds(*parent, i);
            std::cout << (*parent).childs[i] << std::endl;
            buildTree((*parent).childs[i]);
        }
        int eNum = (*parent).getNum();
        for (int j = 0; j < num; j++)
        {
            eNum += (*((*parent).childs[j])).getEnum();
        }
        (*parent).setEnum(eNum);
    }
}
std::shared_ptr<employee> eTree::buildChilds(employee &parent, int i)
{
    std::string name;
    int num;
    std::cout << "Enter the name of " << parent.getName() << "'s " << i + 1 << " child:" << std::endl;
    std::cin >> name;
    std::cout << "How many employee work for " << parent.getName() << "'s " << i + 1 << " child:" << std::endl;
    std::cin >> num;
//  employee child(name, num);
    std::shared_ptr<employee> pchild (new employee(name, num));
//  std::shared_ptr<employee> pchild = std::make_shared<employee>(child);
    return pchild;
}
void more3(employee parent);
void noChild(employee parent);
int main()
{
    using namespace std;
    std::string name;
    cout << "Enter the employee's name: ";
    cin >> name;
    int num;
    cout << "How many employees work for him/her: ";
    cin >> num;
    employee root(name, num);
    shared_ptr<employee> proot = make_shared<employee> (root);
    eTree tree(root);
    tree.buildTree(proot);
    cout << tree.getP()->childs[0] << endl;
    cout << tree.getP()->childs[1] << endl;
    return 0;
}

您可以输入a->2->b->0->c->0,然后查看结果;谢谢

问题是您正在创建root员工的许多副本,并在不同的地方使用这些副本。

在您的主要功能中,尝试以下操作:

shared_ptr<employee> proot = make_shared<employee> (name, num);
eTree tree(proot);
tree.buildTree(proot);

然后更新您的eTree构造函数:

eTree(std::shared_ptr<employee> node) { proot = node; }

我的理由:

在您的代码中,您似乎创建了一个新员工:

employee root(name, num);

然后你制作了一个副本,但它是一个智能指针:

shared_ptr<employee> proot = make_shared<employee> (root);

然后将原件交给eTree:

eTree tree(root);

以及复制到buildTree函数:

tree.buildTree(proot);

因此,构建树为员工的另一个副本构建树

edit:此外,eTree的构造函数还制作了另一个副本作为智能指针,因此最终您将获得原始员工的3个实例。

删除员工的复制构造函数如下,你会看到会发生什么:

employee(const employee&) = delete;

我的代码会编译,你的代码不会。。。


编辑:显示std::make_shared<>()构造新对象的示例代码:

#include <memory>
#include <iostream>
class MyClass {
public:
    MyClass() { std::cout << "    -> MyClass Constructor calledn"; }
    MyClass(const MyClass& other) { std::cout << "    -> MyClass Copy Constructor calledn"; }
};
int main(int argc, char *argv[])
{
    std::cout << "[1] Making MyClassn";
    MyClass myClass;
    std::cout << "[2] Making MyClass Pointern";
    MyClass* myClassPtr = new MyClass();
    std::cout << "[3] Making MyClass Shared using Newn";
    std::shared_ptr<MyClass> myClassSmart1 = std::shared_ptr<MyClass>(new MyClass());
    std::cout << "[4] Making MyClass Sharedn";
    std::shared_ptr<MyClass> myClassSmart2 = std::make_shared<MyClass>();
    std::cout << "[5] Making MyClass Shared from first MyClassn";
    std::shared_ptr<MyClass> myClassSmart3 = std::make_shared<MyClass>(myClass);
    std::cout << "Donen";
}

上面的代码证明std::make_shared<T>()构造了一个新的对象,而不仅仅是为已经存在的对象创建一个共享指针。此外,std::make_shared<Class>(class)使用复制构造函数来创建新对象。

上面在我的电脑上的输出是:

[1] Making MyClass
    -> MyClass Constructor called
[2] Making MyClass Pointer
    -> MyClass Constructor called
[3] Making MyClass Shared using New
    -> MyClass Constructor called
[4] Making MyClass Shared
    -> MyClass Constructor called
[5] Making MyClass Shared from first MyClass
    -> MyClass Copy Constructor called
Done