C++与本地之间的链接引用

C++与本地之间的链接引用,c++,reference,C++,Reference,我有多个引用引用其他引用,但其中一些引用包含在超出范围的对象中,或者在引用到的最终对象之前被销毁 也就是说,被引用的对象的生存期比两者之间的引用更长。现在,访问第一个引用的行为是否未定义 很难解释,但以下代码应该更清楚: #include <iostream> static const int x = 10; struct Q { const int& q = x; }; void foo(int& v) { Q q; v = q.q; }

我有多个引用引用其他引用,但其中一些引用包含在超出范围的对象中,或者在引用到的最终对象之前被销毁

也就是说,被引用的对象的生存期比两者之间的引用更长。现在,访问第一个引用的行为是否未定义

很难解释,但以下代码应该更清楚:

#include <iostream>


static const int x = 10;

struct Q
{
   const int& q = x;
};

void foo(int& v)
{
   Q q;
   v = q.q;
} // q goes out of scope


int main()
{
   int n = 4;
   foo(n);
   std::cout << n;
}

它对我来说似乎工作得很好,而且clang和gcc也不会给我警告。

它没有问题,因为行v=q.q执行一个复制,所以无论q.q引用什么,现在都放在v中。因此,只要q.q在复制时是有效的,这种行为就是有效的。

它没有问题,因为v=q.q行执行复制,所以无论q.q引用什么,现在都放在v中。因此,只要q.q在复制时有效,这种行为就是有效的。

您没有未定义的行为,因为与您的描述显然想说的不同,您的代码中没有悬空引用

让我们回顾一下代码,考虑所有对象的各个生命周期:

此int对象将比所有本地对象寿命更长。它将比示例程序中的所有其他程序都更有效

只要实例本身不超过x对象,Q实例就不会有任何问题。如果您只有本地Q实例,那么就可以了。[1]

在这里,我们有一个来自函数外部的可修改的int对象。它在foo中的名字是v

函数外部的int对象通过q中的引用被分配x对象的值

是的,这并不重要。函数外部的int对象已收到其新值。它不再以任何方式依赖于q甚至x的寿命

这里开始了一个int对象的生命,从main中命名为n

。。。和v来自foo内部

调用之后,foo完成了它的工作,n收到了一个新值

读取n的值。然后,n被销毁。最后,x被销毁。没有问题,没有未定义的行为


[1] 如果在不同的翻译单元中有一个静态Q实例,事情确实会变得更加复杂。

您没有未定义的行为,因为与您的描述显然想说的不同,您的代码中没有悬空引用

让我们回顾一下代码,考虑所有对象的各个生命周期:

此int对象将比所有本地对象寿命更长。它将比示例程序中的所有其他程序都更有效

只要实例本身不超过x对象,Q实例就不会有任何问题。如果您只有本地Q实例,那么就可以了。[1]

在这里,我们有一个来自函数外部的可修改的int对象。它在foo中的名字是v

函数外部的int对象通过q中的引用被分配x对象的值

是的,这并不重要。函数外部的int对象已收到其新值。它不再以任何方式依赖于q甚至x的寿命

这里开始了一个int对象的生命,从main中命名为n

。。。和v来自foo内部

调用之后,foo完成了它的工作,n收到了一个新值

读取n的值。然后,n被销毁。最后,x被销毁。没有问题,没有未定义的行为


[1] 如果在不同的翻译单元中有一个静态Q实例,事情确实会变得更加复杂。

这是合法的。每种情况下的参考是x。对同一个对象有多少个引用并不重要。也就是说,这是非常丑陋的代码。你最好有一个很好的理由来写它。你不能重新绑定引用。v=q.q;只是复制一份。最后,它归结为int n=4;n=10;这是合法的。每种情况下的参考是x。对同一个对象有多少个引用并不重要。也就是说,这是非常丑陋的代码。你最好有一个很好的理由来写它。你不能重新绑定引用。v=q.q;只是复制一份。最后,它归结为int n=4;n=10;
static const int x = 10;
struct Q
{
   const int& q = x;
};
void foo(int& v)
{
   Q q;
   v = q.q;
} // q goes out of scope
int main()
{
   int n = 4;
   foo(n);
   std::cout << n;
}