Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 让局部变量引用其他局部变量是否危险?_C++_Reference_Destructor - Fatal编程技术网

C++ 让局部变量引用其他局部变量是否危险?

C++ 让局部变量引用其他局部变量是否危险?,c++,reference,destructor,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(); } }; 看起来,这可能会导致owner的析构函数对已销毁的owned调用

以这两类为例:

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

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

    int i;
};

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

    Owned& o;

    ~Owner() { o.print(); }
};
看起来,这可能会导致
owner
的析构函数对已销毁的
owned
调用函数,具体取决于它们被销毁的顺序。是否定义了局部变量的销毁顺序,以及如何使两个实例相互引用的情况起作用


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

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

Owner
实际上并不拥有
owned
它只是有一个引用,因此,当它被销毁时,不会调用拥有的析构函数。

局部变量的销毁顺序与创建顺序相反。在您的情况下,您很好,因为
owner
总是在
拥有之前被销毁

§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; } 
};
这将确保两个对象都不会引用不存在的对象


<> p>相互引用对象是非常罕见的。

你所写的东西并不危险,无论如何,C++中相同范围的变量以定义的(反向排序方式)被破坏。然而,像这样的事情是危险的

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

    owner.doSomethingWithOwned();
}

由于owned已不存在,它被强制超出范围。这也适用于将局部变量设置为堆上对象中的引用

那么,如果我以另一种方式声明它们,行为是未定义的?还有第二个问题呢?@SethCarnegie:你如何以另一种方式声明它们?担心的是
owned
将在
owner
之前被销毁,因此后者的析构函数将访问一个悬空引用。函数没有名为
setOwned
:)你是对的。但是,如果你把引用复制到一个类似的构造函数中,你可以看到一个超出范围的对象是如何不被引用的(因为它不存在的)。是的,答案是正确的(AFAIK),除了函数声明。好的,这基本上就是我想的。谢谢。“让两个实例相互引用”我想你的意思是“拥有”和“拥有者”都包含一个相反类型的成员引用。那样做,你真的不可能。但这是因为引用在创建后不能重新分配给新的引用。如果你只是a)切换到指针,b)在构造函数之外执行赋值(将你从特定的时间问题中分离出来),那么你就完全掌握了什么可以得到什么。但以强大的力量p@Michael:只需在构建后分配给
其他
成员即可。我已经有了指针<代码>一个o;两个t&o;o、 其他=&t@Xeo是的。是的,你完全正确。我累坏了。我写这篇文章时正在看OP的代码。(此外,我还可以发誓,在一篇关于相互引用的评论中有一个后续问题。该死,这些编辑发生得太快了。)
int main() {
    Owner owner();
    {
        Owned owned;
        owner.setOwned(owned);
    }

    owner.doSomethingWithOwned();
}