0

我有一个类 A 的实例。它有两个成员,对象 A 和对象 B。我需要创建对象 A 的一个实例(这是一个相当大的对象)和对象 B 的两个实例,然后给出两个实例对象 B 访问该对象 A。他们不需要更改对象 A,他们只需要访问它的信息。

现在,我通过将对象 A 创建为指针,将其传递给对象 B 的两个实例来完成所有工作,这两个实例都有自己的指针,然后指向内存中与对象 A 的指针相同的位置。这很好用,但我认为这是一个很大的不,不,对吧?因为一旦 A 类删除了原始指针,我就会有一些悬空指针,对吧?有一个更好的方法吗?

(仅供参考 - 对象 A 在我需要快速加载时间的程序中一次加载需要几秒钟,这就是为什么我必须只创建一个实例并将其传递给两个对象 B 而不是让对象 B 创建自己的对象 A 的实例。)

4

2 回答 2

2

如果我正确地跟随你,你想要这样的东西:

// Class for "Object A" in your question
class Foo
{
    // ...
};

// Class for "Object B" in your question
class Bar
{
    Foo &foo_;

public:
    Bar(Foo &foo)
        : foo_(foo)
        {}
};

class A
{
    Foo foo_;
    Bar bar1_;
    Bar bar2_;

public:
    A()
        : bar1_(foo_),
          bar2_(foo_)
        {}
};

不使用指针,不使用分配,因此没有悬空指针/引用或内存泄漏。当A被销毁时bar1_bar2_也会与 一起被销毁foo_,因此 的两个实例Bar也不会留​​下任何悬空引用。

于 2012-09-03T14:05:02.567 回答
1

假设“B-things”的寿命不超过“它们都有一个指向的大对象”,那么当“大对象”被删除时,你就不会有一个悬空指针。

如果“A 类的一个实例”将这两个对象都作为数据成员,那么它们将同时被销毁(嗯,与它们在类中声明的顺序相反,但接近于同时) , 所以确保悬空指针永远不会被使用应该是相当容易的。

另一方面,如果你随意传递指向“大对象”的指针,将它们存储在生命周期未知的各种不同的地方,然后删除“大对象”——当然,这是一个禁忌。问题是“不择手段”——您需要保持控制并确保大对象比指向它的对象寿命长。

例如,以下是完全安全的:

struct Big {
    // big stuff
};

struct Little {
    Little(const Big *a) : bigthing(a) {}
    // stuff that uses bigthing
  private:
    const Big *bigthing;
};

struct Foo {
    Big onlybigthing;
    Little firstlittlething;
    Little secondlittlething;
    Foo() : 
        onlybigthing(), 
        firstlittlething(&onlybigthing), 
        secondlittlething(&onlybigthing) 
    {}
};

当然,前提是 的实例Little不会将其指向Big, 的指针分发给任何来请求它的人,然后将其存储在Foo对象的生命周期之外。同样Foo必须避免将实例的副本分Little发给可能存储这些实例的人(以及与它们一起的指针)。

但是你说你的类 A 有两个成员,而这里我有三个(一个Big和两个Little),因为你还说你创建了这两个对象的三个实例。我不明白那是什么意思。

这是另一个安全的例子:

int main() {
    Big big;
    Little little1(&big);
    Little little2(&big);
}

这是安全的第三个示例:

struct Little {
    Little(const std::shared_ptr<Big> &a) : bigthing(a) {}
    // stuff that uses bigthing
  private:
    std::shared_ptr<Big> bigthing;
};

int main() {
    std::shared_ptr<Big> big(new Big());
    Little little1(big);
    Little little2(big);
    big.reset(); // release our shared ownership
    // safely do stuff using little1 and little2

    return 0;
    // on exit, little2 is destroyed first, then when little1 is destroyed
    // it releases the last shared ownership of the instance of `Big`,
    // which is destroyed.
}
于 2012-09-03T14:02:32.010 回答