Does vtkSmartPointer support std::move

As vtkSmartPointer is similar to std::shared_ptr. I use std::move to vtkSmartPointer object. But I find the pointer of the object is NOT null after std::move. Does vtkSmartPointer support std::move? If supported, what’s wrong with my code? Thanks in advance.

I’m using VTK 8.2.0 on Ubuntu18.04 and Windows 10.

This is the part of my source code:

vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(xyz[0][0], xyz[0][1], xyz[0][2]);
points->InsertNextPoint(xyz[1][0], xyz[1][1], xyz[1][2]);
points->InsertNextPoint(xyz[2][0], xyz[2][1], xyz[2][2]);
points->InsertNextPoint(xyz[3][0], xyz[3][1], xyz[3][2]);

vtkSmartPointer<vtkPolyData> quad = vtkSmartPointer<vtkPolyData>::New();
quad->SetPoints(std::move(points));

//points shoud be null, but it still can be used
double normal[3] = {0, 0, 0};
double point1[3] = {points->GetPoint(0)[0], points->GetPoint(0)[1], points->GetPoint(0)[2]};
double point2[3] = {points->GetPoint(1)[0], points->GetPoint(1)[1], points->GetPoint(1)[2]};
double point3[3] = {points->GetPoint(2)[0], points->GetPoint(2)[1], points->GetPoint(2)[2]};

Issue #1: objects handled by vtkSmartPointer are managed by VTK framework so you don’t need to do memory management yourself (move-ing included).

Issue #2: std::move(points) is moving the vtkSmartPointer object, not the vtkPoints object it refers to. vtkSmartPointer objects are small objects, so there is no point in move-ing them

Issue #3: if you move an object, you don’t try to access it after the move. I’m surprised that your program didn’t crash.

vtkSmartPointer recently learned some things about C++11, but it was shortly after the 8.2.0 release:

https://gitlab.kitware.com/vtk/vtk/-/commit/30605cd78d9a36f67dbf7c0c9d54e879d908ce8c

After the next release, std::move on vtkNew, vtkSmartPointer, and vtkWeakPointer should work as expected. For vtkSmartPointer in particular, moving will move the pointer into the destination, clear the source, and not touch the reference counter.

To clarify some points:

This is not true. Though vtkSmartPointers are small, there is a large cost in copying them – making a copy of a smart pointer increases the pointee’s reference count, which involves a ton of virtual calls, atomic operations, and possibly some list traversals. It’s a very heavy operation that does more than just copy some bits.

The original question is asking why the code doesn’t crash, and the usage was just an example of this issue. After the next release, the moved-from pointer will be null and the code will crash (as expected).

1 Like

Yes, vtkSmartPointer<>::operator= is much slower than a pointer copy, but it is still extremely fast: vtkSmartPointer copy takes 300ns, while a regular pointer copy takes 2ns (in debug mode; in release mode, vtkSmartPointer copy takes 45ns, while the simple pointer copy test was removed by compiler optimization; measured by copying then setting a pointer to nullptr 1 million times).

Making std::move release reference in the old pointer is the right thing to do, but performance improvement is expected to be negligible (unless you copy millions of VTK object pointers per second).

Sure, if performance isn’t important, it isn’t important :slight_smile:

But consider that (assuming a 3GHz processor clock), that 45ns overhead just wasted 150 cycles to copy a pointer – and that’s a best case scenario microbenchmark with a warmed up L1 and the branch prediction preconfigured to zip through all of the virtual calls. Throw in a few mispredicted branches and cache misses, and that adds some serious overhead!

For some of the situations where VTK is used, such as stereoscopic VR, where you have to render a scene 120x/second to hit a comfortable 60 fps – that leaves 8ms per render. ~100ns for a pointer copy starts to hurt pretty bad.

It depends on how performance sensitive the application is, for sure, but move semantics are important considerations when using vtkSmartPointers – I wouldn’t discount them so readily :slight_smile: