【问题标题】:How to store pointers to objects that class doesn't own?如何存储指向该类不拥有的对象的指针?
【发布时间】:2021-07-14 15:43:04
【问题描述】:

我正在尝试编写两个类 FooFactory 和 Foo。 FooFactory 在构造函数中初始化一个对象 ToolBox 并将其存储在 unique_ptr 中,因为我希望在工厂被破坏后对其进行清理。 Foo 的所有实例都应该能够使用 ToolBox,因此我在 Foo 的构造函数中将 ptr 传递给 ToolBox 对象并将其存储为裸 ptr。

我是 C++ 开发的新手,所以,我的问题是根据我听到的一般建议提出的:

尽可能避免使用原始指针

  1. 在这种情况下,是否可以使用裸 ptr 来存储 Foo 不拥有的 tool_box 对象?或者我可以使用 smart_ptr 做得更好吗?
  2. 将 ptr 从 FooFactory 类传递到 ToolBox 到每个新对象的模式是正确的还是我可以做的更好?

我的类的伪代码:

class FooFactory {
 public:
  FooFactory() {
    tool_box_.reset(new ToolBox());
  }

  std::unique_ptr<Foo> NewFoo() {
    std::unique_ptr<Foo> foo(new Foo(tool_box_.get());
    return foo;
  }
  std::unique_ptr<ToolBox> tool_box_;
}

class Foo {
 public:
  Foo(ToolBox* tool_box) {
    tool_box_ = tool_box;
  }
 private:
  // Not Owned
  ToolBox* tool_box;
}

【问题讨论】:

  • 原始指针,正如您在代码 sn-p 中所拥有的,适用于非拥有指针。 NewFoo 应该是:std::unique_ptr&lt;ToolBox&gt; NewFoo() {...,因为它返回一个 owned 指针。
  • 通常建议是“避免拥有原始指针”。非拥有的原始指针通常没问题。

标签: c++ pointers smart-pointers


【解决方案1】:

factory 通常永远不会控制对象的生命周期。它应该分发一个适当的指针,最好是std::unique_ptr,调用者确定它的生命周期。

#include <string>
#include <iostream>
#include <memory>

class Box
{
public:
    Box() {}
};

class Foo
{
public:
    Foo(std::shared_ptr<Box> &box)
    : m_box(box)
    {
    }
    virtual ~Foo(){}

    void print()
    {
        std::cout << "Hello World" << std::endl;
    }

protected:
    Box *getBox()
    {
        return m_box.get();
    }

private:
    std::shared_ptr<Box> m_box;
};

class FooFactory
{
public:
    FooFactory()
    {
        m_box = std:make_shared<Box>();
    }

    std::unique_ptr<Foo> CreateFoo()
    {
        return std::make_unique<Foo>(m_box);
    }

private:
    std::shared_ptr<Box> m_box;
};

int main()
{
    FooFactory factory;
    std::unique_ptr<Foo> foo = factory.CreateFoo();

    foo->print();

    return 0;
}

【讨论】:

  • 谢谢,我也想保持工厂的轻量级,但是如果我想让所有的 Foo 类都使用一个通用的工具箱,我该怎么做呢?我应该在 Foo 中使用 java 静态变量之类的东西吗?
  • factory 知道如何构造一个对象。所以这是添加您需要的工具箱的地方。如果Toolbox 是一个“全局”对象并且对于其他对象相同,那么您可以在您的工厂中创建它。
  • 所以factory 应该构造tool_box 但不应该存储它?由于要求是“应该只有一个 tool_box 对象共享 accros Foo 对象的实例”。如果我使用 std::uniqe_ptr 将它传递给创建的每个 Foo 而不将其存储在 factory 对象中 - 我不能让每个 Foo 访问相同的工具箱?
  • 取决于工具箱,您不需要使用共享指针创建它,但是您需要确保工厂的升降时间,因为它包含工具箱。在这种情况下,原始指针就足够了。取决于你的工具箱是如何构建的。
  • 谢谢,有道理。因此,将其存储在 factory 和 Foo 中的 shared_ptr 中,以确保即使 Factory 被删除,Foo 对象仍然可以访问工具箱,并且当最后一个对象消失时,它会被清理。
【解决方案2】:

将非拥有“指针”存储到对象(同时将类与该对象耦合)的一种方法是存储引用(或者可能是 const 引用)而不是指针。

根据我的经验,需要使用该引用初始化类的限制有助于分层设计并简化生命周期管理。

【讨论】:

  • 谢谢,所以我可以肯定地说所有只读的非拥有对象都可以作为 const refs 传递/存储吗?
  • 通常不鼓励引用数据成员。出于在类中存储引用的目的,通常最好使用指向 const 的指针而不是引用数据成员,这几乎总是意味着该类将是不可分配的。
  • 我想说这可能归结为您是否希望可空状态有效。当然,正如你所说,使用必要的构造函数,我认为这仍然可以通过指向 const 的指针来强制执行。
猜你喜欢
  • 2021-05-20
  • 2020-12-06
  • 2019-12-18
  • 2023-02-09
  • 2018-06-03
  • 1970-01-01
  • 2010-11-30
  • 2014-12-19
  • 1970-01-01
相关资源
最近更新 更多