以这两个类为例:
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
上调用函数。是否定义了局部变量的破坏顺序,以及如何使两个实例相互引用的情况?
请原谅我,如果这是常识,我在任何地方都没有读过任何关于它的内容。
答案 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)
这是安全的,本地对象会按照创建它们的相反顺序销毁。