0

我对通过引用相当陌生,我必须确保我正确理解这一点。我必须将我所有的堆内存转换为堆栈内存,因为我的教授这么说,而且我被两个概念困住了。

在类中存储引用的最佳方法是什么?我最初将成员对象作为非指针,但注意到当对象(不是成员对象)从堆栈中弹出时,将在成员变量上调用解构函数。这让我觉得这是一个副本,而不是真正的参考。

这是我最初的一个例子:

class B
{
    public:
        B();
        ~B();
};

class A
{
    private:
        B b;
    public:
        A();
        ~A();
        setB(B& bVar);
};

void A::setB(B& bVar)
{
    b = bVar;
}

我的解决方案是将其更改为指针,因此它不会调用解构器,但我不确定这是否是正确的方法。这是我的解决方案:

class B
{
    public:
        B();
        ~B();
};

class A
{
    private:
        B* b;
    public:
        A();
        ~A();
        setB(B& bVar);
};

void A::setB(B& bVar)
{
    b = &bVar;
}

我的第二个问题有点相关。我不确定当您遇到以下情况时会发生什么:

object1 = object2&. 

object1 是一个副本还是实际上是 object2 的另一个标识符?

4

1 回答 1

3

引用的行为类似于实例的符号别名,并且在某些方面类似于不能(不应该)为空的“指针”。为了便于解释,我将在下面引用它们,就好像它们是指针一样。

当你有 aT&时,这意味着它指向 a T,并且它本身不是一个副本。

当您拥有 aT = T&时,这意味着您将获得一个副本(或副本的副本),具体取决于构造函数或赋值运算符的定义方式。

当您拥有 时R& = L,这意味着您将获得指向L任何内容的副本(前提是允许此操作的赋值运算符)。R&R

关于存储引用的“正确”方式,我至少会问这些问题:

  • 成员引用在包含对象的整个生命周期中保持不变是否可以接受?
  • 包含类型的实例是否总是在成员引用指向的对象之前被销毁?

如果两者都是真的,那么简单地声明并适当地初始化一个成员T&就足够了:

class B
{
    // details...
};

class A
{
    B &_b;
public:

    A(B &b) :
    _b(b)
    {}
};

否则,尽管对您施加了要求,但情况可能需要类似shared_ptr<>或类似的东西。

对存在于堆栈上的对象的引用,反过来又由其他对象持有,这些对象本身可能以这样的方式构造,它们将超过其引用的生命周期,它们只是等待悬空的指针。

考虑复制,或争论堆分配的内存是更好的选择。

如果你不确定你的程序引入的参考网络,你需要重新设计它。

编辑:

重要的是要注意,在传递对函数的引用时(const T&特别是),在某些情况下编译器可以忽略它。例如:当这样的函数被内联时,可以用更有效的寻址逻辑代替引用,而不是要求它们是指针。

在这方面,它们不是指针。

于 2013-11-14T10:25:22.013 回答