例如
struct A
{
void foo() {};
};
struct B
{
B() {}
void setA(A* a) { mA = a; }
foo() { mA->foo(); }
A *mA;
};
A
内有一个B
关联(只是一个地址)。 B::mA
不得为null
。我经常忘记setA
并引入错误。有什么好的做法可以避免它?那么setA
如何?
void B::setA(A& a) { mA = &a; }
答案 0 :(得分:6)
最好的方法是首先避免使用指针。如果必须使用指针,请考虑使用智能指针,例如std::unique_ptr
或std::shared_ptr
。始终,总是初始化指针,要么为null(除非你使用智能指针),要么是你已分配的东西。 总是 总是在使用之前检查null。
答案 1 :(得分:3)
第一个也是最重要的是永远不要留下指针
初始化。至少,将其设置为nullptr
(或NULL
in
pre-C ++ 11)在构造函数中,所以你至少可以测试它的有效性
后面。
除此之外,很大程度上取决于它应该指向的内容:
如果它指向的生命周期保证超出范围 你的对象的生命周期(在两个方向:它存在于你的 对象是构造的,并且在您的对象之后将继续存在 destructed),传递它作为构造函数的引用,并采取 初始化指针的引用地址。
如果它指向的生命周期可能要等到你之后才开始
构造对象,然后必须将指针设置为null
构造函数,在setA
函数中赋值给它,并验证它是否正确
每次要使用它时都不为空。
如果指向的生命周期可能在您的对象之前结束
破坏了,然后你需要某种观察者模式的变体,
通知您的对象已经破坏了指向的对象,
并将指针设置为null。在这种情况下,您还必须检查
每次使用前为null。在过去,我使用了ManagedPtr
为此,但它不是一个通用的解决方案。 (它会使指针无效,
但如果指针在地图或某物中,通常是
例如,它不会从地图中删除条目。)
如果对象的生命周期应影响其生命周期
指向对象,然后你应该考虑使用std::shared_ptr
。
我发现在实际代码中这种情况非常罕见,但它们确实发生了。
(请注意,如果您使用std::shared_ptr
,则必须非常非常
小心。您只能从任何给定的构造一个std::shared_ptr
原始指针没有遇到问题。在我们自己的代码库中,我们已经
被禁止std::shared_ptr
,并使用我们自己的侵入性参考计数
指针,以避免这样的问题。 std::shared_ptr
已经过了
精心设计,以最大限度地发挥悬挂指针的风险
多次删除同一个对象。)
答案 2 :(得分:1)
"我经常忘记setA并引入错误。"
因此强迫自己通过构造函数设置它:
struct B
{
public:
B(A *a) : ma(a) {}
private:
A *mA;
};
让foo
检查一下:
foo()
{
if (mA)
mA->foo();
else
// handle it, throw exception, ignore, ...!
}
答案 3 :(得分:1)
如果对象始终在B
object:
struct B
{
B(A& a) : mA(a) {}
foo() { mA.foo(); }
A& mA;
};
A a;
B b(a);