在c++中,当我通过引用传递一个对象时,它超出了作用域
What happens in C++ when I pass an object by reference and it goes out of scope?
我认为这个问题最好用我刚刚写的一小段代码来问:
#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的编译器时,超出作用域的变量还没有被"清理",所以内存仍然是"有效的"(但行为是未定义的)。然而,微软的编译器更积极地清理了它,这个错误很明显。
您有一个悬空引用,这会导致未定义的行为。
-
看这里:局部变量的内存可以在其作用域之外访问吗?
-
它几乎会工作,因为你没有虚函数,你不访问BasicClass的字段:你调用的所有方法都有静态绑定,'this'永远不会被使用。所以你永远不会真正访问"未分配内存"
- 在构造函数中输入对象时C++类成员作用域
- 在 C++ 中使用 "transform" 会给出一个错误,指出这未在作用域中声明
- 无法从派生类型的作用域访问另一个实例的受保护成员
- 混合指向已分配对象和作用域对象的指针
- 在一个作用域中推送五个对象指针,然后检查对象的布尔值是否为 false,会给出错误
- 类的堆分配对象是否在其作用域之后但在 C++ 中调用其析构函数之前处于活动状态
- 在c++中,全局作用域中只允许"表达式"初始化全局对象.我在哪里可以在标准中找到这个
- 无法访问类作用域中的对象
- C++11 Lambda闭包通过引用涉及一个堆栈变量,该变量离开作用域是允许的,但得到了未定义的行为
- 在提升作用域出口中调用对象函数
- 如何在 c++ 中创建一个可调试的文件作用域(静态?)类
- 用LD_PRELOAD和C++中的全局作用域对象加载堆分析器
- 将对象的属性传递到方法时出现作用域问题.(opencv相关)
- 有没有一个C++版本在循环结束后将在for循环初始化中声明的变量保留在作用域中
- 在调用函数的作用域中构造返回的对象
- 本地对象的作用域
- 函数作用域的静态非 Pod 对象初始化
- C++有必要删除主作用域末尾动态分配的对象
- 正在获取另一个函数作用域中的参数值
- 在c++中,当我通过引用传递一个对象时,它超出了作用域