【问题标题】:How could I get address of the target object in smart pointer?如何在智能指针中获取目标对象的地址?
【发布时间】:2021-12-26 19:17:32
【问题描述】:

我正在尝试通过间接指针来实现链表,它在TED Talk上引入。

我参考felipec's implementation on github并通过原始指针制作了一个版本,这是github link

这是完整代码的一部分,_find是一个可以找到目标节点的间接指针的函数,即*indirect == target node

//...
struct Node {
    int data;
    Node *next;
    Node()
        : data(0), next(nullptr) {}
    Node(int _d, Node *_next = nullptr)
        : data(_d), next(_next) {}
    ~Node() { puts("~Node"); }
};
//...

List::Node **List::_find(const int target)
{
    Node **indirect = &head;
    while (*indirect && (*indirect)->data != target)
        indirect = &(*indirect)->next;

    return indirect;
}

我想做一个智能指针版本。我在Node 中使用std::unique_ptr 作为next 指针,在List 中使用std::shared_ptr 作为head 指针。

但是在Node **indirect = &head部分,我不知道如何通过智能指针来设计它,我写了这个:

//...
struct Node {
    int data;
    std::unique_ptr<Node> next;
    Node()
        : data(0), next(nullptr) {}
    Node(int _d, std::unique_ptr<Node> &_next)
        : data(_d), next(std::move(_next)) {}
    ~Node() { puts("~Node"); }
};
//...

List::Node **List::_find(const int target)
{
    Node **indirect = &(head.get());
    while (*indirect && (*indirect)->data != target)
        indirect = &(*indirect)->next;

    return indirect;
}

显然,Node **indirect = &amp;(head.get()) 不是一个好主意,因为 get 函数返回它指向的右值。但是我需要的是指向目标的指针对象,代码甚至无法编译。

因此,有两个问题

  1. 如何在智能指针中获取目标对象的地址?

  2. 我是否以正确的方式使用智能指针?我应该将shared_ptr 更改为unique_ptr,还是不使用智能指针?

感谢任何其他补充和建议。

【问题讨论】:

  • @selbie 是的,我希望它返回一个指向指针的指针。

标签: c++ linked-list smart-pointers


【解决方案1】:

如何在智能指针中获取目标对象的地址?

我认为您的意思是“智能指针中的指针地址”,因为目标对象的地址正是您使用.get() 获得的地址。 std::unique_ptr 没有提供任何接口直接访问它的指针成员,所以这是不可能的。

我是否以正确的方式使用智能指针?我应该将 shared_ptr 更改为 unique_ptr,还是不使用智能指针?

使用std::unique_ptr 是正确的做法。您不需要shared_ptr,因为任何给定节点都不会有两个所有者。

在您的第一个代码中,indirect 是指向 Node/List 结构中的原始指针的指针。由于您将这些更改为智能指针,indirect 也应该成为指向智能指针的指针:

std::unique_ptr<List::Node> *List::_find(const int target)
{
    std::unique_ptr<Node> *indirect = &head;
    while (*indirect && (*indirect)->data != target)
        indirect = &(*indirect)->next;

    return indirect;
}

虽然返回引用会更惯用:

std::unique_ptr<List::Node> &List::_find(const int target)
{
    std::unique_ptr<Node> *indirect = &head;
    while (*indirect && (*indirect)->data != target)
        indirect = &(*indirect)->next;

    return *indirect;
}

(我假设这是一个私有帮助函数,实际上不是List 类的接口,在这种情况下,任何一个实现都会出现问题。)

【讨论】:

  • 感谢您的回答 :) 这种设计是否违反了使用unique_ptr 的某些规则?或者它没有取得所有权就可以了?
  • @Mes 它不会破坏原始指针版本也不会破坏的任何规则。重要的是,返回的指针仅在删除包含指向指针的节点之前有效,并且如果在列表中添加/删除元素,则返回的指针在两次间接后指向的节点可能会发生变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多