The Object Lifecycle encompasses the full lifespan of an object in memory — from initial allocation and construction, through usage, to final destruction and memory reclamation. Master runtime memory allocation, reference counting, garbage collection, and memory leak prevention across C++, Java, and Python.
Languages allocate memory differently between Stack (automatic scope management) and Heap (dynamic runtime lifetime).
class Student {
String name;
Student(String name) { this.name = name; }
}
public class Main {
public static void main(String[] args) {
// Stack holds reference 's' -> Heap holds Student object
Student s = new Student("Raj");
System.out.println(s.name);
}
}
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
string name;
Student(string n) : name(n) {}
};
int main() {
// Stack object (automatic memory cleanup on scope exit)
Student s1("Raj");
cout << s1.name << "\n";
// Heap object (dynamic allocation — MUST be deleted manually)
Student* s2 = new Student("Aman");
cout << s2->name << "\n";
delete s2; // Explicit memory reclamation
return 0;
}
class Student:
def __init__(self, name):
self.name = name
def main():
# Variable 's' in local stack frame -> Heap object Student
s = Student("Raj")
print(s.name)
if __name__ == "__main__":
main()
Reference counting tracks the number of pointers/handles pointing to an object. When count drops to zero, the object can be safely reclaimed.
std::shared_ptr for automatic reference counting and
std::weak_ptr for breaking cycles.
class Demo {}
public class Main {
public static void main(String[] args) {
Demo a1 = new Demo(); // Reference count = 1
Demo a2 = a1; // Reference count = 2
a1 = null; // Reference count = 1
a2 = null; // Reference count = 0 -> Unreachable, eligible for GC
}
}
#include <iostream>
#include <memory>
using namespace std;
class Demo {};
int main() {
// shared_ptr tracks reference count automatically
shared_ptr<Demo> a1 = make_shared<Demo>(); // count = 1
shared_ptr<Demo> a2 = a1; // count = 2
a1.reset(); // count = 1
a2.reset(); // count = 0 -> Destructor runs, heap memory freed
return 0;
}
class Demo:
pass
def main():
a1 = Demo() # Reference count = 1
a2 = a1 # Reference count = 2
a1 = None # Reference count = 1
a2 = None # Reference count = 0 -> Reclaimed immediately by CPython
if __name__ == "__main__":
main()
How objects exit memory differs fundamentally between deterministic manual/RAII destruction (C++) and managed runtime garbage collection (Java / Python).
public class Main {
public static void main(String[] args) {
System.out.println("JVM GC runs automatically via Mark-Sweep-Compact.");
// System.gc() is only a request to JVM, not a guarantee!
System.gc();
}
}
#include <iostream>
using namespace std;
class Demo {
public:
Demo() { cout << "Constructor called\n"; }
~Demo() { cout << "Destructor called (Deterministic Cleanup)\n"; }
};
int main() {
{
Demo obj; // Stack object
} // Destructor runs IMMEDIATELY here when exiting scope
return 0;
}
import gc
class Demo:
def __del__(self):
print("Finalizer __del__ called")
def main():
obj = Demo()
del obj # Reclaims object if ref count hits zero
gc.collect() # Trigger manual cyclic GC sweep
if __name__ == "__main__":
main()
A Memory Leak occurs when allocated memory is no longer needed by the program but cannot be reclaimed because unintentional references persist.
import java.util.ArrayList;
import java.util.List;
class MemoryLeakExample {
// Static collection lives for entire application lifetime!
private static List<Object> staticList = new ArrayList<>();
public void leak(Object obj) {
staticList.add(obj); // Objects added here NEVER get garbage collected!
}
}
class MemoryLeakExample {
public:
void leak() {
int* ptr = new int(10);
// Forgetting delete ptr -> Heap memory leak!
}
};
class MemoryLeakExample:
static_list = [] # Class-level list lives for program lifetime
def leak(self, obj):
self.static_list.append(obj) # Objects never freed!
A Cyclic Reference forms when two or more objects reference each other in a loop.
std::shared_ptr instances keep reference counts
> 0 forever, causing a guaranteed memory leak. Solution: Break the loop using
std::weak_ptr for back-references.
gc
module) detects and reclaims unreferenced cycles.
class Node {
Node next;
}
public class Main {
public static void main(String[] args) {
Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a; // Cyclic reference formed
a = null;
b = null; // Java GC safely reclaims both nodes despite cycle!
}
}
#include <iostream>
#include <memory>
using namespace std;
struct Node {
// Solution: Use weak_ptr for 'next' or back-reference to break cycle!
weak_ptr<Node> next;
};
int main() {
shared_ptr<Node> a = make_shared<Node>();
shared_ptr<Node> b = make_shared<Node>();
a->next = b;
b->next = a; // weak_ptr prevents ref count deadlocks
return 0;
}
class Node:
def __init__(self):
self.next = None
def main():
a = Node()
b = Node()
a.next = b
b.next = a # Cyclic reference (reclaimed by Python cyclic GC)
a = None
b = None
if __name__ == "__main__":
main()
| Aspect | Java | C++ | Python |
|---|---|---|---|
| Memory Allocation | Heap (all objects) + Stack (reference variables) | Stack (automatic) OR Heap (new / smart pointers) |
Heap (runtime managed) + Stack (scope handles) |
| Destruction Model | Automatic Garbage Collector (Mark-Sweep-Compact) | Deterministic Destructors (RAII) / manual delete |
Automatic Ref Counting + Cyclic GC |
| Ref Count Cycles | Safely reclaimed via GC Root graph traversal | Memory Leak! (Requires std::weak_ptr) |
Reclaimed by secondary cyclic GC module |
| Primary Leak Cause | Static collections / unremoved event listeners | Unfreed heap pointers (new without delete) |
Growing global lists/dicts / unevicted caches |
What occurs in C++ when two objects hold std::shared_ptr references to each
other in a loop?
How does Java handle cyclic references between unreachable objects?
4 Stages ⇒ Creation (Allocation) — Usage — GC / Destruction — Memory Reclaimed
Stack ⇒ Automatic scope allocation ; ultrafast ; automatic cleanup on scope exit (C++ default)
Heap ⇒ Dynamic runtime allocation ; requires manual delete or smart pointers
(C++) or GC management (Java/Python)
C++ ⇒ Deterministic RAII destructors (~Demo()) ; manual delete ;
std::shared_ptr ref counting
Java ⇒ Reachability GC (Mark, Sweep, Compact) from GC Roots ; System.gc() is
non-guaranteed request
Python ⇒ Primary Reference Counting + secondary cyclic GC
C++ Cycle Leak ⇒ shared_ptr loops keep ref count > 0 forever ; fix with
std::weak_ptr
Java / Python Cycle Handling ⇒ Reclaimed automatically via GC graph traversal / cyclic collector
Java / Python Leak Cause ⇒ Unintentional static collection references or lingering event listeners
Primary source: Oracle Java Tutorials — Garbage Collection Tuning, cppreference — Smart Pointers & RAII & Python Docs — gc module. Ask me anything that's unclear.
Questions? Ask your agent — you can follow up on any concept, quiz answer, or how this applies to a specific coding problem. Review the Java glossary or syntax quick reference for a compressed overview.