I have been having trouble trying to understand how shared pointers work from the perspective of member variables. There are a lot of good questions on SO that explain shared pointers and how/when to use them (this, this, and this, among others). However, I've been struggling to understand how they work when we are dealing with class instance variables, particularly those that are containers (like std::vector
).
I have a workflow that involves
- Reading data from a file
- Storing that data in a container in a class
- Accessing, modifying, and passing around that data in instances of that containing class
I am trying to understand if (and where) my code is doing needless copying, or if my passing of a constant reference is good enough. After doing some reading, I am inclined to think that I should be creating the objects once on the heap and passing shared pointers around rather than constant references, but I can't articulate why.
I have pasted parts of my program below in (roughly) their current implementation. My questions are:
- For the
PointCloud
class, should I instead be storing shared pointers toPoint3D
objects in the_data
vector? This way, during the filtering operation, I can populate my_inliers
and_outliers
PointCloud variables by filling their respective_data
member variables with shared pointers to the appropriate Point3D objects? - For
Scene
class and theFilter
class, am I better off with making thePointCloud
type member variables shared pointers toPointCloud
? I am pretty sure my current getter implementations return copies, and thesePointCloud
objects can contain millions ofPoint3D
objects, so they're not small. Would this be better than returning a constant reference (as I do inPointCloud::getData()
?
Ultimately I think the root of my question comes down to: should I do nearly all of my Point3D object creation on the heap and just store shared pointers in my container class member variables? Essentially this would be using a sort of "shared memory" model. If so, what would the efficiency improvement be? If not, why not?
Here are some components of my program.
(Note: in reality implementations are not actually all inlined. I just did that here for brevity).
scene.h
#include "pointcloud.h"
#include "point3D.h" // just defines the Point3D class
class Scene
{
private:
// Other member variables...
/** Pointcloud */
PointCloud _pointcloud;
public:
// ...Public functions...
inline PointCloud getPointCloud() const; // Return point cloud
inline void readPoints3D(const std::string &path_to_file);
};
PointCloud Scene::getPointCloud() const { return _pointcloud; }
void Scene::readPoints3D(const std::string &path_to_file)
{
std::ifstream file(path_to_file.c_str());
// Run through each line of the text file
std::string line;
std::string item;
while (std::getline(file, line))
{
// Initialize variables id, x, y, z, r, g, b from file data
Point3D pt(id, x, y, z, r, g, b); // Create Point3D object
_pointcloud.addPoint(pt); // Add point to pointcloud
}
file.close();
}
pointcloud.h
#include "point3D.h"
#include <vector>
class PointCloud
{
private:
/** PointCloud data */
std::vector<Point3D> _data;
public:
// Public member functions
inline std::vector<Point3D> & getData();
inline const std::vector<Point3D> & getData() const;
inline void addPoint(const Point3D &pt);
};
const std::vector<Point3D> & PointCloud::getData() const { return _data; }
std::vector<Point3D> & PointCloud::getData() { return _data; }
void PointCloud::addPoint(const Reprojection::Point3D &pt)
{
_data.push_back(pt); // Add the point to the data vector
}
filter.h
#include "pointcloud.h"
// Removes 3D points from a pointcloud if they don't meet certain conditions
class Filter
{
private:
// Good points that should stay in the pointcloud
PointCloud _inliers;
// Removed points
PointCloud _outliers;
public:
Filter(const PointCloud &pointcloud) // Constructor
void filterPointCloud(); // Filtering operation
inline PointCloud getInliers();
inline PointCloud getOutliers();
}
Filter::Filter(const PointCloud &pointcloud) :
_inliers(pointcloud), _outliers(PointCloud()) {}
PointCloud getInliers() { return _inliers; }
PointCloud getOutliers() { return _outliers; }
driver.cpp
#include "scene.h"
#include "pointcloud.h"
#include "filter.h"
// Some function that writes my pointcloud to file
void writeToFile(PointCloud &cloud);
int main()
{
Scene scene;
scene.readPoints3D("points3D_file.txt");
PointCloud cloud = scene.getPointCloud();
Filter f(cloud);
f.filterPointCloud();
writeToFile(f.getInliers());
writeToFile(f.getOutlier());
}