docs / guide / The Cajeta Guide
Chapters — 10. Allocation
- Introduction
- 0. Introduction
- 1. Installation
- 2. Kick the tires
- 3. Your first project
- 4. Running your application
- 5. Debugging
- 6. Keywords
- 7. Comments
- 8. Native types
- 9. Type kinds
- 10. Allocation
- 11. Ownership & borrowing
- 12. Control flow
- 13. Strings & formatting
- 14. Templates & wildcards
- 15. Lambdas & captures
- 16. Operator overloading
- 17. Inheritance
- 18. Annotations & synthesis
- 19. DI & aspects
- 20. Error handling
- 21. Reflection
- 22. Differentiation
- 23. Code coverage
- 23. Profiling
- 24. Notebooks
10 — Allocation
Every class instance is created with an explicit placement prefix: stack or
heap. There is no new. Omitting the prefix at a constructor call is a
compile error — placement is always visible at the allocation site.
public class Point {
public int32 x;
public int32 y;
public Point(int32 x, int32 y) {
this.x = x;
this.y = y;
}
public int32 distSq() {
return this.x * this.x + this.y * this.y;
}
}
Point onStack = stack Point(3, 4); // this frame; dropped at scope exit
Point onHeap = heap Point(5, 12); // heap block; freed by the drop chain
Point named = stack Point { x: 1, y: 2 }; // aggregate initializer
Run it: AllocationDemo.
One type, either storage
Point is the same type wherever it lives. The storage mode is a property of
the value, not the type — the borrow checker tracks lifetime as metadata.
A method that takes Point accepts both:
public class Meter {
public int32 measure(Point p) {
return p.distSq();
}
public void run() {
Point s = stack Point(3, 4);
Point h = heap Point(5, 12);
int32 a = this.measure(s);
int32 b = this.measure(h);
}
}
There is no separate pointer or value flavor of a class, and no slicing: class instances always pass and return by reference.
When to pick which
stackwhen the value lives and dies inside the current method or block. No allocation call; the instance drops at the closing}.heapwhen the value must outlive the frame: it is returned to the caller, stored in a field or collection, or handed to another owner with#(next chapter). The heap block is freed automatically when its owner goes out of scope — there is nodelete.
The compiler enforces the boundary. Returning a stack-allocated local from a method is a compile error — the frame it lives in is gone before the caller can look at it:
public Point make() {
Point p = stack Point(1, 2);
return p; // ERROR — stack value cannot escape its frame
}
Heap values never leak either way: if nothing transfers ownership out, the drop chain reclaims the block at the owner’s scope exit. Cleanup on both the normal and the exception path is covered in chapter 11.
A third placement, shared, exists inside GPU kernels for workgroup-shared
memory; it is covered with the compute material. Full semantics:
MemoryModel and
UnifiedClasses.
Next: Ownership & borrowing.