如何在指针关联时编写无错误的代码?

时间:2013-09-21 12:13:09

标签: c++ pointers

例如

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; }

4 个答案:

答案 0 :(得分:6)

最好的方法是首先避免使用指针。如果必须使用指针,请考虑使用智能指针,例如std::unique_ptrstd::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:

之前初始化,则使用reference作为第一选择
struct B
{
    B(A& a) : mA(a) {}    
    foo() { mA.foo(); }    
    A& mA;
};

A a;
B b(a);