返回可能在C ++中分配在堆栈上的成员时,最佳的指针/引用类型是什么?

时间:2019-01-31 18:43:27

标签: c++ pointers reference

为了说明我的问题,我举了一个例子:

#include <iostream>

using namespace std;


struct A
{
  void doSomething (){
      cout << "Something\n";
  }
};


struct B
{
  A a;

  A *getA ()
  {
    return &a;
  }
};


int
main ()
{

  B *b = new B ();
  A *a = b->getA ();


  // POINT 1
  if (nullptr != a)
    {
      a->doSomething ();
    }

  delete b;
  b = nullptr;

  // POINT 2
  if (nullptr != a)
    {
      a->doSomething ();
    }

  return 0;
}

这可以在我的机器上编译并运行,但没有错误,但是,如果您检查代码,则确实存在在标记为“ POINT 2”的注释之后的行上悬挂有指针的问题。

由于b被删除,所以a现在无效(因为它被b的权限删除了)。

因此,我可以使用共享指针来解决此问题,但是即使删除了a,也将保留b的实例,而且我将无法分配{{1} }。这是我要避免的两件事。相反,我只是想知道a是否仍然有效。

我也可以使用唯一的指针,但是我只能有一个a实例,这也不是我想要的,我想要指向a的指针的许多副本。

那么是否存在一些允许我执行此操作的指针/引用类型?有什么理由为什么这是个好主意?

3 个答案:

答案 0 :(得分:3)

您刚刚发现了所有权语义的奇观:)

如何解决此问题取决于您的应用程序的设计:您需要什么以及想要实现什么。

在这种情况下,如果您确实要共享对象的所有权,请使用std::shared_ptr保留剩余的指针数的引用计数,以便最后一个指针删除该对象。如果您只需要检查对象是否还活着,但又不想让它活得比需要的时间更长,则可能是std::weak_ptr

但是,请注意(滥用)共享指针可能是不良设计的标志。


顺便说一下,您的A a;成员没有分配到堆栈中(即标题错误)。

答案 1 :(得分:3)

唯一想到的使用标准库的可行解决方案是使用std::weak_ptr()-它可以在不持有对象所有权的情况下检查对象的有效性。这是有价格的-您必须使用std::shared_ptr来保持其所有权。尽管可以为具有自动存储持续时间和noop删除器的对象创建std::shared_ptr,但只有在我确实需要这样做的情况下,我才会这样做,因为这种方法容易出错并且无法达到智能指针的目的。

答案 2 :(得分:1)

最好的方法是不公开a

您的B是界面。给它您需要执行的功能。让它继续调用a上需要执行的任何操作,以实现该目标。

然后删除getA(),并将a设为私有。

现在,它已完全封装,并且调用范围无法像这样!”

无需指针或动态分配;很好,老式的OOP。