在c++中,当我通过引用传递一个对象时,它超出了作用域

What happens in C++ when I pass an object by reference and it goes out of scope?

本文关键字:一个对象 作用域 引用 c++      更新时间:2023-10-16

我认为这个问题最好用我刚刚写的一小段代码来问:

#include <iostream>
using namespace std;
class BasicClass
{
public:
    BasicClass()
    {
    }
    void print()
    {
        cout << "I'm printing" << endl;
    }
};
class FriendlyClass
{
public:
    FriendlyClass(BasicClass& myFriend) :
        _myFriend(myFriend)
    {
    }
    void printFriend()
    {
        cout << "Printing my friend: ";
        _myFriend.print();
    }
private:
    BasicClass& _myFriend;
};
int main(int argv, char** argc)
{
    FriendlyClass* fc;
    {
        BasicClass bc;
        fc = new FriendlyClass(bc);
        fc->printFriend();
    }
    fc->printFriend();
    delete fc;
    return 0;
}

使用g++代码可以很好地编译和运行:

$ g++ test.cc -o test
$ ./test
Printing my friend: I'm printing
Printing my friend: I'm printing

然而,这不是我所期望的行为。我以为在第二次呼叫fc->printFriend()时会出现某种失败。我对引用传递/存储工作方式的理解是否不正确,或者这只是碰巧在小范围内工作,并且可能会在更复杂的应用程序中爆炸?

它的工作原理与指针完全相同:使用指向不再存在的对象的东西(指针/引用)是未定义的行为。它可能看起来是工作的,但它可能随时中断。

警告:下面是一个快速的解释,为什么这样的方法调用似乎可以在几个场合工作,只是为了提供信息的目的;在编写实际代码时,您应该只依赖于标准所说的

至于你正在观察的行为:在大多数(所有?)编译器上,方法调用被实现为带有隐藏的this参数的函数调用,该参数引用方法将要操作的类的实例。但是在您的情况下,this指针根本没有被使用(函数中的代码不引用任何字段,并且没有虚拟调度),因此(现在无效)this指针不使用并且调用成功。

在其他情况下,即使它引用的是一个作用域外的对象,因为它的内存还没有被重用(尽管析构函数已经运行,所以该方法可能会发现对象处于不一致的状态),它也可能看起来有效。

同样,你不应该依赖这些信息,它只是让你知道为什么这个调用仍然有效。

当您存储对已结束其生命周期的对象的引用时,访问它是未定义的行为。所以任何事情都有可能发生,它可以工作,它可以失败,它可以崩溃,就像我说的,它可以订购披萨

未定义行为。根据定义,您不能假设代码运行时将发生什么。编译器可能还没有清除bc所在的内存,但你不能指望它。

我曾经在一个程序中修复过同样的错误。当使用Intel的编译器时,超出作用域的变量还没有被"清理",所以内存仍然是"有效的"(但行为是未定义的)。然而,微软的编译器更积极地清理了它,这个错误很明显。

您有一个悬空引用,这会导致未定义的行为。

  1. 看这里:局部变量的内存可以在其作用域之外访问吗?

  2. 它几乎会工作,因为你没有虚函数,你不访问BasicClass的字段:你调用的所有方法都有静态绑定,'this'永远不会被使用。所以你永远不会真正访问"未分配内存"