-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PCL_COMMON: removing default constructors/destructors #3440
PCL_COMMON: removing default constructors/destructors #3440
Conversation
There are some merge conflicts. Please resolve them (in another commit) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! What do you think about extending the changes to all members in the classes you have touched?
/** \brief Empty destructor */ | ||
virtual ~PointRepresentation () {} | ||
virtual ~PointRepresentation () = default; | ||
//TODO: check if copy and move constructors / assignment operators are needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we follow the rule of 5 here and just go ahead and default them? Will there be anything bad about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At a first glance I would say no. But I don't have a complete view of the entire code base
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few pitfalls in just declaring them defaults, specially in exception unsafe code. It might be better not to have them declared than to declare buggy defaults. Maybe a work for another PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please expand, why defaults are buggy? And also, how implicit declared destructor (i.e. destructor created by the compiler when user does not declare one) is any different by the default one?
What pitfalls are you referring to when code is not exception safe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how implicit declared destructor ... is any different by the default one?
That's not what I was referring to. Your edit is perfect. I was commenting on my own statement of "what's the issue with blind rule of 5".
What pitfalls are you referring to when code is not exception safe?
Essentially, during copy, if there is an error, the rollback should result in the same state as before attempted copy. But with a) potentially self-copy b) copy of structs with resource owning semantics c) other similar corner cases, the rule of 5 might not be a good idea to apply blindly because the defaults do a element-wise operations. There might be scenarios where based on usage, we might have to do a copy into local variable before moving the resources and local variables to ensure that if copy fails, rollback is trivial.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point - b), a) not really - nonetheless I would say that this might happen when your class has non-trivially copyable elements, but in the case of PODs or classes that hold std::string
s or std::vector<int>
s, probably rule of 5 ( or even 7 ) is just fine.
I know even std::string
copy constructor might fail with std::bad_alloc
, but again, running out of memory it's like an atomic bomb dropped in front of your house: who cares if the windows were closed or not (i.e. destructors are called or not ) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are meandering out of context of the PR. But this is as good place as any.
running out of memory it's like an atomic bomb dropped in front of your house
bad_alloc
isn't called just due to OOM. It's also called when
- a single allocation is larger than the one allowed by the allocator (eg: differing implementations of malloc). <-- most common reason
- allocation takes too much time and it'll impact the "real-time"ness of the application. In soft real-time systems, page swaps required for a large allocation can take time which results in a throw (all custom malloc support maximum time to wait) <-- common in robotics
- application has run out of it's quota of memory (not the OS). This approach is frequently used in sandboxes and extra memory is given to application to clean itself or to recover (via custom api calls) <-- common in cloud based virtualization
- there's a custom memory management (FreeRTOS, distributed memory, etc.) which can throw
bad_alloc
for other reasons too <-- common in virtualization, hypervisors
Running out of memory is a very rare scenario for bad_alloc
. Case 1 (common case) is essentially atom bomb for common users because it's not recoverable (by design or bad-calculations leading to the point) but not for all users.
That was the idea, but unfortunately there are some stuff that need to be changed in order to accomplish it. Some matrices and vectors are initialized with identity matrices or other special matrices by calling static functions. AFAIK those functions need to be marked as |
Force pushing every-time causes lack of knowledge of what's updated. |
sorry about that, next time I will make temporary commits, so that author or maintainer can squash them into one before merging |
Apparently old compilers don't like the modifications wrt Eigen static functions and templates
I wonder what's going wrong in parsing. It's weird that the compiler thinks we are creating a variable |
I wonder if some simple aliasing, something like
would fix the problem. Because it really looks like a bug in the compiler, doesn't it? |
Sounds like a good idea. Could you try that in the docker image (or the CI)? Image is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Please rebase and squash as appropriate
This commit: - adds initiliazition for the non-static members - removes default constructors, destructors - removes from constructors all the calls to default member constructors - adds aliases in vector_average to avoid odd errors in old compilers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant to review this PR but apparently was late to the party. I just highlighted a number of places where destructors should not be required.
//-----CONSTRUCTOR&DESTRUCTOR----- | ||
/** Constructor - dimension gives the size of the vectors to work with. */ | ||
VectorAverage (); | ||
/** Destructor */ | ||
~VectorAverage () {} | ||
~VectorAverage () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for this destructor to not have been removed? I see no copy/move ctors/assignments.
@@ -65,6 +65,7 @@ namespace pcl | |||
|
|||
/** \brief Destructor. */ | |||
virtual ~StopWatch () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This destructor can also be erased. It's a base class with no virtual methods.
{ reset (); } | ||
|
||
/** Destructor */ | ||
~TransformationFromCorrespondences () { }; | ||
~TransformationFromCorrespondences () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here. Base class, with no custom copy/move ctors/assignments nor virtual methods.
|
||
/** \brief Constructor. */ | ||
inline Correspondence (int _index_query, int _index_match, float _distance) : | ||
index_query (_index_query), index_match (_index_match), distance (_distance) | ||
{} | ||
|
||
/** \brief Empty destructor. */ | ||
virtual ~Correspondence () {} | ||
virtual ~Correspondence () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one also does not require declaring the dtor at all.
/** \brief Empty destructor. */ | ||
virtual ~PointCorrespondence3D () {} | ||
virtual ~PointCorrespondence3D () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also remove this one.
@@ -143,7 +140,8 @@ namespace pcl | |||
Eigen::Affine3f transformation; //!< The transformation to go from the coordinate system | |||
//!< of point2 to the coordinate system of point1 | |||
/** \brief Empty destructor. */ | |||
virtual ~PointCorrespondence6D () {} | |||
virtual ~PointCorrespondence6D () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this one.
|
||
/** \brief True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields). */ | ||
bool is_dense; | ||
bool is_dense = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: PCLPointCloud2
is initialized with is_dense
set to false but this one is set to true
:/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not nice, but probably also not critical. I think we should change the default in PCLPointCloud2
because hardly anyone constructs that type of point cloud "by hand".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you confirm what you wrote? You state one thing but your argument seems to point in the other direction. I interpreted what you wrote as
I think we should not change the default in
PCLPointCloud2
because hardly anyone constructs that type of point cloud "by hand".
PCLPointCloud2
comes from ROS messages and these usually means actual sensors which naturally have nans, while the PointClouds
are very often handcrafted. Which would actually mean, this was a well thought decision and their difference is intentional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I indeed meant what I wrote. My thought is that since PCLPointCloud2
comes from ROS message, the default-constructed value of this field does not make any difference, it will be set to whatever value the message had. Similarly, when you call toPCLPointCloud2()
to create a blob point cloud,is_dense
will be set to that of the source cloud.
{} | ||
|
||
/** \brief Destructor. */ | ||
virtual ~PointCloud () {} | ||
virtual ~PointCloud () = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one can also be removed, same reasons as all the other ones.
Sorry. I didn't realize 😅 . We can revert and continue working on this. Or a new one? |
Just a new one, assuming of course you agree with the items I pointed out. |
Unneeded virtual dtors should be removed. It's good to not pay for what we don't use. |
This commit: