在我的工作中,我遇到了一个错误,可以描述如下。 有两个类,A类和B类:
class A
{
public:
void print(){}
};
class B
{
A* a;
public:
void init(A* _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
A* a;
B* b;
b->init(a);
// some code .....
delete a; // line 1
a = NULL;
// some code .....
b->PrintWithA(); // line 2
对象“b”对对象“a”的状态一无所知。在第1行中,“a”对象已被删除,但在第2行,我们继续使用它。当有很多代码时,很容易犯这样的错误。 我的问题是以下 - 用于避免一些错误的approch?我想我可以使用观察者模式 - 但我认为这是不合理的昂贵解决方案。 感谢的。
答案 0 :(得分:0)
你应该使用弱ptr(http://en.cppreference.com/w/cpp/memory/weak_ptr)
基本上你可以为B级提供一个弱的ptr A。
每当有时间访问A时,您可以尝试锁定弱ptr以查看它是否仍然有效。
#include <memory>
class A
{
public:
void print(){}
};
class B
{
std::weak_ptr<A> a;
public:
void init(std::weak_ptr<A> _a) {
a = _a;
}
void PrintWithA()
{
if (auto spt = a.lock()) {
spt->print();
}
}
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>();
std::unique_ptr<B> b = std::make_unique<B>();
b->init(a);
// some code .....
a = nullptr;
// some code .....
b->PrintWithA(); // line 2
return 0;
}
答案 1 :(得分:0)
为了防范这种情况,要么B在构造对象B时需要拥有A的生命周期,要么需要计算A引用。
C ++ 11我认为有一个共享指针的概念来维护引用,并且如果有人有引用,它将阻止对象A被删除。见std::shared_ptr
如果您不使用C ++ 11,则boost::shared_ptr
基本上会执行相同的操作。但是你需要我个人不喜欢使用的升级库,但它取决于你。
像这样使用它们:
typedef std::shared_ptr<A> A_ptr;
A_ptr a = new A();
class B
{
A_ptr a;
public:
void B(A_ptr _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
否则你可以自己把东西放在一起。有点像:
class A
{
public:
A(){
ref_count = 1;
}
void print(){}
void grab() {
ref_count++;
}
void release() {
ref_count--;
if (ref_count <= 0)
~A();
}
private:
int ref_count;
~A(){
delete this;
}
};
在B区内你分配指针并调用grab();
而不是打电话给删除(因为它是私人的而无法工作)你打电话 a-&gt;指针上的release()。
现在这并不是特别棒,因为你不能使用这种形式:
A a;
所以它并不理想。但是,如果您使用的某些编译器没有shared_ptr,并且您不介意限制,则可以使用此或其形式。通常,使用 shared_ptr 。
答案 2 :(得分:-2)
首先,说A* a;
的行应该是A* a = new A;
。
在c ++中,您需要明确地对此感知进行编码,而不是自动完成。
您可以做的一件事是检查_a
中PrintWithA
是否为NULL,但如果您确保在delete[]
之后始终将指针设置为NULL,则无法执行此操作他们(你已经完成了)