proper way to return objects from functions ? (allocation question)

New user question and problem. I’m using the Polygon1 example to learn the basics and I ran into an issue. I wanted to create a routine that returned a points object to subsequently create the polyline (a “factory” maybe ?).

The following works fine:

vtkPoints *closed_polygon(void)
{
  // This doesn't work. apparently due to reference counting not sure
  // what best practice is but it might be smart pointers.
  
  // vtkNew<vtkPoints> points;
  vtkPoints* points = vtkPoints::New();

  points->SetNumberOfPoints(6);
  double c = std::cos(vtkMath::Pi() / 6); // helper variable
  points->SetPoint(0, 0.0, -1.0, 0.0);
  points->SetPoint(1, c, -0.5, 0.0);
  points->SetPoint(2, c, 0.5, 0.0);
  points->SetPoint(3, 0.0, 1.0, 0.0);
  points->SetPoint(4, -c, 0.5, 0.0);
  points->SetPoint(5, -c, -0.5, 0.0);

  cout << "points:" << points << "\n";
  return points;
}

and in main()

...
  vtkPoints *points;
  
  points = closed_polygon();
  cout << "points:" << points << "\n";
  cout << points->GetNumberOfPoints() << "\n";

yielding the following output

points:0x5adfb1cd7c60
points:0x5adfb1cd7c60
6

but if I do the following.

vtkPoints *closed_polygon(void)
{
  // This doesn't work. apparently due to reference counting not sure
  // what best practice is but it might be smart pointers.
  
  vtkNew<vtkPoints> points;
  // vtkPoints* points = vtkPoints::New();

  points->SetNumberOfPoints(6);
  double c = std::cos(vtkMath::Pi() / 6); // helper variable
  points->SetPoint(0, 0.0, -1.0, 0.0);
  points->SetPoint(1, c, -0.5, 0.0);
  points->SetPoint(2, c, 0.5, 0.0);
  points->SetPoint(3, 0.0, 1.0, 0.0);
  points->SetPoint(4, -c, 0.5, 0.0);
  points->SetPoint(5, -c, -0.5, 0.0);

  cout << "points:" << points << "\n";
  return points;
}

and back in main()

  vtkPoints *points;
  
  points = closed_polygon();
  cout << "points:" << points << "\n";
  cout << points->GetNumberOfPoints() << "\n";

The routine runs but does not draw the polygon correctly.
I then put in the following code to help debug

  vtkPoints *points;
  double x[2];
  
  points = closed_polygon();
  cout << "points:" << points << "\n";
  cout << points->GetNumberOfPoints() << "\n";
  points->GetPoint(0, x);
  
  cout << x[0] << "\n";

The program segfaults on the printing of x[0]. Interestingly it prints the number of points, 6, correctly. And if I go back to allocating the pointer using

vtkPoints::New()

in the closed_polygon function, the code works.
In reading through the forums I get the impression that

  vtkNew<vtkPoints> points;

is generating a traced pointer and I’m wondering if leaving the function is ending the scope of points and that causes the problem, but I’m not exactly sure.
And generally I’m wondering what the best practice is when you would like to return objects from functions.

Thanks for reading :slight_smile:

You are just returning a pointer and when the function goes out of scope the pointer in the caller is undefined.

You need a function declaration something like:

vtkNew<vtkClass> fn()
{
  vtkNew<vtkClass> x;
  // Do something with it.
  return x;
}

Then to call it:

   auto z = fn();

Reference counting done by vtkNew ensures that the returned object does not go out of scope after the function returns.

There are lots of examples of this approach in the VTK Examples, for example, look at vtkNew<vtkPolyData> ReadPolyData(fs::path const& path); in GradientBackground

Thank you so much !

I think I understand. Have I essentially returned a pointer to an object which has been allocated on the stack ? (my c++ is very rusty :wink: )