c++pointersobject-lifetimetemporary-objects

Pointer to temporary object


Why does this code work correctly?

struct A {
    std::string value = "test"s;
    
    A() { std::cout << "created" << std::endl; }
    ~A() { std::cout << "destroyed" << std::endl; }
};

int main() { 
    A* ptr = nullptr;
    
    {
        A a;
        ptr = &a;
    }
    
    std::cout << ptr->value << endl; // "test"
}

output:

Or this example:

struct A {
    const std::string* str = nullptr;
    
    A(const std::string& s) : str(&s) {}
};

int main()
{
    A a = std::string("hello world");
    std::cout << *a.str;

    return 0;
}

output:

In the first case, it seemed to me that when object A was destroyed, the content would become invalid, but I was able to retrieve the string.

In the second case, I took rvalue by constant reference, but extending the life of the object should work as long as the reference is valid. I thought that after the constructor worked, the string should have been destroyed. Why is this not happening?


Solution

  • Both codes have undefined behavior.

    Here:

    {
        A a;
        ptr = &a;
    }
    
    std::cout << ptr->value << endl; // "test"
    

    ptr becomes invalid once a goes out of scope and gets destroyed.

    Similar in the second example, you are also dereferencing an invalid pointer because the temporary string is gone after the call to the constructor.

    C++ does not define what happes when you do things that are not defined (makes sense, no? ;). Instead it is rather explicit about saying that when you do certain wrong things then the behavior of the code is undefined. Dereferencing an invalid pointer is undefined. The output of the code could be anything. A compiler is not required to diagnose undefined behavior, though there are features and tools that can help. With gcc it is -fsanitize=address that detects the issue in both your codes: https://godbolt.org/z/osc9ah1jo and https://godbolt.org/z/334qaKzb9.