【问题标题】:Passing a smart pointer as argument inside a class: scoped_ptr or shared_ptr?在类中传递智能指针作为参数:scoped_ptr 还是 shared_ptr?
【发布时间】:2009-03-17 18:13:00
【问题描述】:

我有一个在一个公共方法中创建对象的类。该对象是私有的,对类的用户不可见。该方法然后调用同一类中的其他 private 方法并将创建的对象作为参数传递:

class Foo {
   ...
};

class A {
   private:
      typedef scoped_ptr<Foo> FooPtr;

      void privateMethod1(FooPtr fooObj);

   public:
      void showSomethingOnTheScreen() {
          FooPtr fooObj(new Foo);
          privateMethod1(fooObj);
      };
};

我相信在这种情况下正确的智能指针应该是 scoped_ptr,但是,我不能这样做,因为如果这样使用 scoped_ptr 会使类不可复制,所以我应该使用这样的方法:

void privateMethod1(FooPtr& fooObj);

privateMethod1 不存储对象,也不保留对它的引用。只需从 Foo 类中检索数据。

正确的方法可能是根本不使用智能指针并在堆栈中分配对象,但这是不可能的,因为它使用的库不允许堆栈上的对象,它们必须在堆上。

毕竟,我仍然对 scoped_ptr 的真正用法感到困惑。

【问题讨论】:

  • 我对“不允许堆栈上的对象”的库感到好奇。对象是否在堆上的库内与工厂一起分配?库是否拥有指针的所有权并将其删除?不能使用堆栈分配对象的原因是什么?

标签: c++ class boost smart-pointers


【解决方案1】:

另一种可能性是将对象创建为 static_ptr 以便于内存管理,但只需将原始指针传递给其他私有方法:

void privateMethod1(Foo *fooObj);

void showSomethingOnTheScreen() {
  scoped_ptr<Foo> fooObj(new Foo);
  privateMethod1(fooObj.get());
};

【讨论】:

    【解决方案2】:

    我会在 showSomethingOnTheScreen 中使用 scoped_ptr,但将原始指针(或引用)传递给 privateMethod1,例如

    scoped_ptr fooObj(new Foo);
    privateMethod1(fooObj.get());

    【讨论】:

    • 这是我的真实猜测,但是否推荐这种做法?如果是这样,我会这样做
    【解决方案3】:

    在这里使用简单的 std::auto_ptr 因为你不能在堆栈上创建对象。而且你的私有函数最好只接受原始指针。

    真正的用法是你不必捕获所有可能的异常并手动删除。

    事实上如果你的对象没有修改对象并且你的API返回对象肯定你最好使用

    void privateMethod1(const Foo& fooObj);
    

    并将对象传递到那里

    privateMethod1(*fooObj.get());
    

    【讨论】:

    • 这与 scoped_ptr 完全相同,只是它不会强制您将方法参数声明为引用。但是如果你不这样做,它会以令人惊讶的方式中断(一旦 privateMethod1 返回,fooObj 将是一个 Null 指针,即使你想用它做更多的事情)。
    • 当然同意某事。如果 scoped_ptr 显然是更好的选择,为什么还要使用 auto_ptr?并非有意转让所有权。
    • 伙计们,我的项目没有进展。所以这就是我提出这种stl解决方案的原因。您在哪里看到“所有权转让”?
    • nowhere :) 但与 scoped_ptr (明确禁止所有权转让)相比,有 :) 当我认为没有可用的 scoped_ptr 时,确实可以使用它。我不想说它不是(我认为两者都不是 :))但我想我们只是想告诉爱迪生这件事:)
    • 现在我的意思是如果他已经使用 scoped_ptr 为什么他现在决定使用 auto_ptr?这就是我评论它的原因。
    【解决方案4】:

    我对“它使用的库不允许堆栈上的对象,它们必须在堆上”的评论表示怀疑。

    为什么?这通常意味着必须以某种特殊方式释放它们 - 所以这些解决方案可能都不起作用。

    【讨论】:

    • @Earwicker 我们使用的编译器是 Borland C++,我们使用的库是与 C++ 捆绑的 VCL GUI 库。这很快就会改变,但我现在必须坚持这一点。出于某种原因,VCL 必须在堆上分配,我不知道为什么。
    • 可能这意味着库具有工厂方法,这些方法返回指向已创建对象的指针并将所有权传递给用户。
    • 您确定要删除这些对象吗?我从未使用过 VCL,但我有一个模糊的概念,即它会在删除父组件时自动删除组件。
    【解决方案5】:

    在这种情况下,您只需更换分配机制。
    在堆上创建对象,但将对象作为引用传递给私有方法。

    class A {
       private:
          void privateMethod1(Foo& fooObj);
    
       public:
          void showSomethingOnTheScreen() {
              scoped_ptr<Foo> fooObj(new Foo);
              privateMethod1(*(fooObj.get()));
          };
    };
    

    【讨论】:

      猜你喜欢
      • 2015-01-24
      • 1970-01-01
      • 2020-07-10
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      相关资源
      最近更新 更多