Creating SDL2 Buttons

C++ Dangling References: Lifetimes and Undefined Behavior

What happens if an object is destroyed before a reference to it, like if UI is destroyed before Button?

Abstract art representing computer programming

First, recall that a reference in C++ is essentially an alias for an existing object. When you initialize a reference, it becomes bound to that object.

int value{10};
int& ref{value}; // ref is now an alias for value

ref = 20; // This changes 'value' to 20
std::cout << value; // Outputs 20

Unlike pointers, references cannot be "null" (they must be initialized to refer to a valid object) and cannot be "reseated" to refer to a different object after initialization.

Dangling References and Undefined Behavior

The problem arises when the object that the reference is bound to ceases to exist (i.e., its lifetime ends) while the reference itself still exists. This creates what's known as a dangling reference.

Consider our Button and UI example:

// UI.h
// ... (Contains Button C { *this, ... } )

// main.cpp
int main() {
  // ...
  { // Inner scope starts
    UI UIManager; // UIManager created on the stack
    // UIManager creates Button C, passing '*this'
    // Button C now holds a reference to UIManager

    // ... Use UIManager and its Button C ...

  } // Inner scope ends - UIManager is destroyed!

  // If Button C somehow still exists out here
  // (e.g. if it was dynamically allocated and
  // not deleted, or moved), its 'UIManager'
  // reference is now DANGLING.

  // Accessing the dangling reference leads to
  // UNDEFINED BEHAVIOR
  // button_c.UIManager.SomeFunction(); // CRASH? GARBAGE?
  // ...
  return 0;
}

If the UI object UIManager is destroyed (for example, because it goes out of scope or the object containing it is deleted) but a Button object still holds a reference (UIManager) to that now-destroyed UI object, that reference becomes dangling.

Using a dangling reference leads to undefined behavior (UB). This is one of the most dangerous situations in C++ because the compiler doesn't necessarily give you an error. Anything could happen:

  • Your program might crash immediately.
  • Your program might continue running but produce incorrect results.
  • Your program might appear to work correctly sometimes and crash mysteriously at other times.
  • It might corrupt memory in subtle ways that cause problems much later in the program's execution.

Lifetime Management is Key

This highlights the critical importance of managing object lifetimes. When you create relationships where one object holds a reference (or pointer) to another, you must ensure that the referenced object lives at least as long as the reference itself.

In typical UI scenarios like the lesson:

  1. The parent (UI) usually owns its children (Button).
  2. When the parent (UI) is destroyed, it should ensure its children (Button instances it created) are also destroyed before the parent's own destruction completes.

If the Button objects are direct members of the UI class (as in the lesson's final code), C++ handles this automatically. When UIManager is destroyed, its members (A, B, C) are destroyed first.

However, if you were managing Button objects dynamically (e.g., storing Button* in a std::vector), the UI destructor would need to explicitly delete those buttons to avoid memory leaks and potential dangling references/pointers if something else still held a pointer/reference to them.

In summary, using a reference after the object it refers to has been destroyed results in undefined behavior. Proper object lifetime management is essential to prevent dangling references.

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

This course includes:

  • 110 Lessons
  • 92% Positive Reviews
  • Regularly Updated
  • Help and FAQs
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2025 - All Rights Reserved