从唯一指针列表中返回原始指针

问题描述 投票:0回答:2

我有一个类 (

A
),它将拥有另一个类 (
B
) 的一组实例的内存。
A
会将
B
的实例存储为一组
std::unique_ptr<B>

我希望

A
能够返回对这些 B 对象的一组原始指针的引用(即我不希望任何所有权转移)。最好的方法是什么?

class A
{
private:
    std::set<std::unique_ptr<B>> _Bs;
public:
    std::set<B*>& getBs() { ???? };
}

我可以创建一个新向量:

class A
{
private:
    std::set<std::unique_ptr<B>> _Bs;
    std::set<B*>                 _rawBs;
public:
    std::set<B*>& getBs() { return _rawBs; };
}
std::set<B*>
A::A()
{
    std::transform(_Bs.begin(), 
                   _Bs.end(), 
                   std::inserter(_rawBs, _rawBs.begin()), 
                   [](auto uniq_ptr) { uniq_ptr.get(); }
    
}

但是将这些指针存储两次似乎有点笨拙......

c++ memory-management unique-ptr ownership
2个回答
0
投票

你应该添加一个成员函数:

const std::set<std::unique_ptr<B>>& getBs() {
    return m_bs;
}

有几点需要注意:

  • 不幸的是,您无法返回类似

    std::span
    的内容,并且必须返回对
    const std::set
    的引用。这会泄露更多的实现细节,但这是必要的,因为集合不是连续的容器。

  • 您仍然可以返回一个包含所有指针副本的

    std::vector<B*>
    ,但这会更昂贵。

  • A

    const std::set
    只允许您以
    const std::unique_ptr
    的形式访问内部元素,因此尽管暴露了
    std::unique_ptr
    ,但没有所有权被转移。所有权转让还需要能够修改
    std::unique_ptr

  • 不应将名称

    _Bs
    用于数据成员,因为下划线后跟大写字母可构成保留标识符。请参阅在 C++ 标识符中使用下划线的规则是什么?。 最流行的成员命名方案(如果您给他们前缀或后缀)是前缀
    m_


0
投票

我希望 A 能够返回对 B 对象的一组原始指针的引用

这是一个糟糕的计划。如果调用者修改了该集合,您会怎么做?

您可以按值返回指针视图。

class A
{
private:
    std::set<std::unique_ptr<B>> Bs;
public:
    auto getBs() const { 
        return Bs | std::views::transform([](auto & ptr){ return ptr.get(); }); 
    };
};

如果您的

std::unique_ptr<B>
保证不为空,您可以通过将
ptr.get()
替换为
*ptr
来返回引用视图。

© www.soinside.com 2019 - 2024. All rights reserved.