C++ Linked Lists   «Prev  Next»
Lesson 13

Useful Classes for Dynamic Structures Conclusion

This module discussed two useful class implementations of dynamic structures
  1. a "safe array" that performs its own bounds checking and
  2. a singly linked list.

In addition, you learned how to use an efficient object disposal routine for large aggregate types.
In particular, you learned how to:
  1. Implement a bounds-checking array using classes
  2. Group classes in a hasa relationship
  3. Implement a singly linked list using classes
  4. Use reference counting for efficient object disposal

Efficient Object Disposal Routine

It's necessary to use an efficient object disposal routine, usually involving a custom destructor, for large aggregate types in C++ in the following situations:
  1. Dynamic Memory Allocation
    • Ownership of resources: If your large aggregate type contains members that directly hold pointers to dynamically allocated memory (using `new`), you *must* implement a destructor to release this memory correctly using `delete`. Otherwise, you'll have memory leaks.
    • Example: A large struct containing multiple dynamically allocated arrays.
  2. Resource Management (Beyond Memory)
    • External resources: If members of your aggregate type manage resources like file handles, network connections, or other system-level objects, a destructor is essential. You need to make sure these resources are closed or released properly when the object is destroyed.
    • Example: A struct holding a file handle, a network socket, and a database connection.
  3. Performance Optimization
    • Expensive copy operations: Large aggregate types, even without dynamic memory or resources, can be expensive to copy by default (member-by-member copy). If your code involves frequent copying or moving of these objects, a custom copy constructor and move constructor along with a destructor might be necessary to optimize performance.
    • Example: A large struct containing several large data structures like vectors or maps.
  4. Enforcing RAII (Resource Acquisition Is Initialization):
    • Deterministic cleanup: The RAII principle in C++ strongly encourages tying resource management to object lifetimes. A well-defined destructor ensures that resources are released automatically when the object goes out of scope, preventing leaks and making resource management easier to reason about.
Example Code (Dynamic Memory)
struct LargeData {
    int* large_array;

    LargeData() : large_array(new int[1000000]) {} // Constructor allocates

    ~LargeData() { delete[] large_array; }       // Destructor cleans up
};

SEMrush Software