局部变量引用其他局部变量是危险的吗?

时间:2012-03-22 17:26:36

标签: c++ reference destructor

以这两个类为例:

struct Owned {
    Owned() : i() { }

    void print() { cout << ++i << endl; }

    int i;
};

struct Owner {
    Owner(Owned& o) : o(o) { }

    Owned& o;

    ~Owner() { o.print(); }
};

以这种方式使用它们是否危险?

int main() {
    Owned owned;
    Owner owner(owned);
}

似乎,根据它们被破坏的顺序,这可能导致owner的析构函数在被破坏的owned上调用函数。是否定义了局部变量的破坏顺序,以及如何使两个实例相互引用的情况?

请原谅我,如果这是常识,我在任何地方都没有读过任何关于它的内容。

4 个答案:

答案 0 :(得分:5)

本地变量以与创建相反的顺序销毁。在你的情况下,你很好,因为owner将永远在owned之前销毁。

§6.6 [stmt.jump] p2

  

从范围退出(无论多么已完成)时,在该范围内构建的具有自动存储持续时间(3.7.3)的对象将按其构造的相反顺序销毁。

但是,如果您可以在施工后重新分配拥有的成员,则必须小心。

  

如何处理两个实例相互引用的情况?

不要让它们在析构函数中相互访问。或者首先要弄清楚究竟是谁被摧毁,也许是通过回调或标志传递。例如:

struct two;
struct one{
  two* other;

  one(two* o = nullptr) : other(o) {}
  ~one(){ if(other) other.other = nullptr; }
};

struct two{
  one* other;
  two(one* o = nullptr) : other(o) {}
  ~one(){ if(other) other.other = nullptr; } 
};

这将确保两个对象永远不会引用不存在的对象。

无论如何,相互引用对象非常罕见。

答案 1 :(得分:1)

Owner实际上并不拥有owned它只是引用它,所以当它被销毁时,自己的析构函数将不会被调用。

答案 2 :(得分:1)

你所写的内容并不危险,C ++中相同范围的变量以定义的(反向排序的方式)被破坏。然而,这样的事情很危险,

int main() {
    Owner owner();
    {
        Owned owned;
        owner.setOwned(owned);
    }

    owner.doSomethingWithOwned();
}

由于拥有不再存在,因此被迫超出范围。这也适用于将局部变量设置为堆上对象的引用。

答案 3 :(得分:0)

这是安全的,本地对象会按照创建它们的相反顺序销毁。