Could someone explain to me the difference between the following allocations? In the example, I use a VTK array.
vtkNew<vtkDoubleArray> method1;
vtkSmartPointer<vtkDoubleArray> method2;
auto method3 = vtkDoubleArray::New();
Questions:
If I start a project now in C++17, is there a reason to use vtkNew or vtkSmartPointer instead of new or the smart pointers of the C++ standard library?
As for method 3, what is the advantage of using a factory method to allocate a VTK object?
In general, why are VTK objects allocated dynamically, and not on the stack using vtkDoubleArray method4;? Specifically for VTK arrays, why not follow the approach of std::vector, i.e. normally we allocate it on the stack, but its buffer is allocated on the heap?
vtkNew increments the reference count of vtkDoubleArray and decrements it when it goes out of scope. Useful if you need a short-lived VTK object in the context of a function, for example.
vtkSmartPointer<vtkDoubleArray> method2;
This declares a vtkSmartPointer<vtkDoubleArray> but does not initialize it with a vtkDoubleArray. Increments the reference count of the vtkDoubleArray when it is assigned an object allocated by vtkSmartPointer<vtkDoubleArray>::New() and decrements the reference count of the previously assigned object when assigned a different object or nullptr. It’s helpful for memory management of longer-lived objects.
auto method3 = vtkDoubleArray::New();
Raw pointer. You need to explicitly decrement the reference count when done with the object with vtkDoubleArray->Delete(), otherwise you will have a memory leak.
Yes. VTK has a garbage collection system that won’t be used if you use new (which is disallowed because VTK object constructors are protected) or C++ standard library smart pointers.
VTK has a class override mechanism that can instantiates appropriate subclasses when a general class is created. For instance vtkRenderer::New() will typically create a vtkOpenGLRenderer under the covers to use the OpenGL rendering backend.
It’s in keeping with the design decision that all VTK objects (with very few exceptions) live on the heap and you pass pointers to them around. You also get the benefits of VTK’s garbage collection by deriving vtkDoubleArray from vtkObject, which essentially forces vtkDoubleArray to be allocated on the heap.
Does it mean that an std::unique_ptr will not release the resources if a VTK object goes out of scope? Probably this is the case, according to what I found in the coding conventions. Could you please provide me other resources that explain memory allocations in VTK? I am especially interested in when VTK makes a copy of a passed object, and how it can be avoided (exposing the buffer).
Is it documented somewhere (user/dev docs or a blog post), I would like to understand the basic philosophy?
Each VTK object has an internal reference counter, essentially making raw pointers to VTK objects usable as shared pointers. This mechanism was introduced decades before modern smart pointers were added to C++ and has similar capabilities. You can learn some more background and best practices here: Slicer/Docs/developer_guide/advanced_topics.md at main · Slicer/Slicer · GitHub