开发者

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

I think this question is best asked with a small code snippet I just wrote:

#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)
{
    Friendly开发者_运维问答Class* fc;
    {
        BasicClass bc;
        fc = new FriendlyClass(bc);
        fc->printFriend();
    }
    fc->printFriend();
    delete fc;
    return 0;
}

The code compiles and runs fine using g++:

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

However, this is not the behavior I was expecting. I was expecting some sort of failure on the second call to fc->printFriend(). Is my understanding of how the passing/storing by reference works incorrect or is this something that just happens to work on a small scale and would likely blow up in a more sophisticated application?


It works exactly as for pointers: using something (pointer/reference) that refers to an object that no longer exists is undefined behavior. It may appear to work but it can break at any time.

Warning: what follows is a quick explanation of why such method calls can seem to work in several occasions, just for informative purposes; when writing actual code you should rely only on what the standard says

As for the behavior you are observing: on most (all?) compilers method calls are implemented as function calls with a hidden this parameter that refers to the instance of the class on which the method is going to operate. But in your case, the this pointer isn't being used at all (the code in the function is not referring to any field, and there's no virtual dispatch), so the (now invalid) this pointer is not used and the call succeeds.

In other instances it may appear to work even if it's referring to an out-of-scope object because its memory hasn't been reused yet (although the destructor has already run, so the method will probably find the object in an inconsistent state).

Again, you shouldn't rely on this information, it's just to let you know why that call still works.


When you store a reference to an object that has ended its lifetime, accessing it is undefined behavior. So anything can happen, it can work, it can fail, it can crash, and as it appears I like to say it can order a pizza.


Undefined behavior. By definition you cannot make assumptions about what will happen when that code runs. The compiler may not be clearing out the memory where bc resides yet, but you can't count on it.

I actually fixed the same bug in a program at work once. When using Intel's compiler the variable which had gone out of scope had not been "cleaned up" yet, so the memory was still "valid" (but the behavior was undefined). Microsoft's compiler however cleaned it up more aggressively and the bug was obvious.


You have a dangling reference, which results in undefined behavior.


  1. look here: Can a local variable's memory be accessed outside its scope?

  2. It will almost will work, since you have no virtual functions, and you don't acces fields of BasicClass: all methods you call have static binding, and 'this' is never used, so you never actually access "not allocated memory".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜