MtxVec maintains a pre-allocated object pool (cache) for TVec and TMtx objects. CreateIt/FreeIt borrow and return objects from this pool — they do not allocate/free memory.
Why use CreateIt/FreeIt:
- Objects are pre-allocated at startup → near-zero allocation cost
- Pool objects have pre-allocated memory → no heap allocation for small sizes
- Essential for block processing loops where objects are created/destroyed rapidly
- Used with TVec/TMtx (pool-managed types), not with Vector/Matrix (value types)
Basic pattern:
// C++ (no finally: free on the error path and on the normal path)
TVec* a = nullptr;
TVec* b = nullptr;
TVec* c = nullptr;
CreateIt(a, b, c); // borrow 3 objects from pool
try
{
a->Size(1000);
b->Size(1000);
a->RandUniform();
c->Sin(a);
c->Add(b);
}
catch (...)
{
FreeIt(a, b, c); // return to pool, then let the exception propagate
throw;
}
FreeIt(a, b, c); // return to pool (not freed from memory)
Rules:
- Always pair CreateIt with FreeIt in try/finally
- Never mix CreateIt objects with regular constructor objects
- CreateIt objects are for LOCAL variables only — do not store in fields
- FreeIt does not destroy the object — it returns it to the pool for reuse
C++ has no finally, so in C++ rule 1 means two FreeIt calls: one in a catch (...) block that rethrows and one after the try block, as in the example above. FreeIt sets the pointer to nullptr (rule 5). Vector and Matrix need neither: their destructors return the object to the pool on every path out of the scope, exceptions included.
When to use what:
| Scenario | Use | Why |
|---|---|---|
| General code | Vector / Matrix | Automatic lifetime, operator support |
| Block processing | CreateIt/FreeIt with TVec/TMtx | L1 cache discipline, fast pool reuse |
| Temporary in tight loop | CreateIt/FreeIt | No GC pressure, predictable lifetime |
| Fields / properties | Vector / Matrix | Automatic management, no manual free |
In C++, Vector, Matrix, VectorInt and MatrixInt use this object cache, as in Delphi — the value type borrows an object from the pool on first use, and its destructor returns it. new TVec() creates an object outside the pool; free it with delete.
Pool monitoring:
// Check for leaks — should be 0 after all FreeIt calls
TMtxVecPoolItem* pool = Controller->Pool[Controller->GetPoolIndex()];
int vecLeaks = pool->Vec->GetCacheUsedCount();
int mtxLeaks = pool->Mtx->GetCacheUsedCount();
In C++ pooling is not tied to a compiler switch: MTXVEC_RANGE_CHECKING adds the element-accessor checks and leaves the cache on. To turn CreateIt/FreeIt into real heap allocations that a leak checker can see, empty the cache at startup with Controller->SetVecCacheSize(0, 0) and Controller->SetMtxCacheSize(0, 0).