为了说明我的问题,我举了一个例子:
#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
的指针的许多副本。
那么是否存在一些允许我执行此操作的指针/引用类型?有什么理由为什么这是个好主意?
答案 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。