Conversation
|
🚀 New build available for commit |
| mean(wf.mean), | ||
| dirtyZerns(wf.dirtyZerns) | ||
| dirtyZerns(wf.dirtyZerns), | ||
| regions(wf.regions), |
There was a problem hiding this comment.
This makes me nervous (line 49 - the regions copy)
- Does it do a deep copy?
- Previous behavior you got a regions member that was empty and ready to be filled with fresh regions. Does the existing code expect this everywhere or does it not care? Did you check all the times he adds regions and might we get doubled regions?
There was a problem hiding this comment.
On the other hand this might fix some bug I didn't really know was easy to fix that I forgot about. Maybe regions can get lost after certain operations and maybe that's bad.
There was a problem hiding this comment.
Thank you for your review; your comments are always spot on.
The copy constructor does deep copy of the matrix. it would be very strange to not deep copy everything else. Or one should create a dedicated function.
- Yes it does a deep copy (not immediately but if it ever gets modified) https://doc.qt.io/qt-6/qlist.html#QList-2
- I have not found any place where there is risk of reusing old data that shouldn't.
My conlusion : this modification shall not introduce a bug. If it ever does it will just confirm that code relied on some sort of "side effects".
Now that I looked deeper in the code I think it might be worse it to make the copy constructor =default it won't do the deep copy anymore so i will touchup the code where required (I believe it's only 2 places). Everything will be much more explicit and we will rely on 0 side effect.
There was a problem hiding this comment.
Ok in addition I also confirmed it does not fix any bug...
|
🚀 New build available for commit |
|
Hi @gr5 , I dug a bit more on this topic. Today this is the curretn usage of copy And I see 2 solutions:
Could you advise ? |
|
I love #2 where you have "shallowCopy()" and "deepCopy()". To me that makes things so much more clear. I do not like using libraries where this is hard to figure out. Does opencv already have 2 functions: "copy()" and "clone()"? I don't know which is which if so. I prefer the shallow and deep explanation. To me it's clear. @githubdoe - what do you think? leave it as is but add comments that say "shallow copy"? Or create 2 functions to make the code more clear? |
|
Touching that is very dangerous. Pick option #3. Unless you find something broken for the user. George. At one time OpenCV documentation was very clear that when working with cv::Mat an "=" and the like did not do a deep copy and the clone() was the way to make a deep copy. Now it is harder to find the documentation with AI intervention and not showing it. Wavefront tired to be memory and CPU efficient when working with them and passing them around. Changing how that works is a huge risk. |
Well @atsju looked at it pretty carefully so I'm not too worried. I would recommend as a minimum commenting where it's not clear which are deep and which are shallow copies. The first line of code mentioned by @atsju above is this:
does not use "clone" yet it does a deep copy. I'm the one who added that comment. About a year ago. Perhaps my mention of "clone()" was a distraction as we are talking about class wavefront, not cv::mat which is what I was talking about just above. |
|
Well typically this one comment is probably incorrect. The line = is just a shallow copy. Not a deep copy. The rest of matrixes is copied later but not here. My proposal is really just rename the 7 occurrence of While I agree there is 0 bug today, this renaming would be without risk and should -in my opinion- ease maintenance and code understanding. Maybe I could just write the code and you decide after that if you want to keep it or not. Now that I have checked everything 5 times, it will be really easy to implement. |
|
Okay so there we go. It must at least copy the things in my comment (wavelength, diameter). I assume I put in a breakpoint and saw it do the copy. It's not clear to me if it uses the operator= versus the copy contstructor or... what it does there. Without putting in a breakpoint on the next line and in the copy constructor and checking what gets copied I wouldn't know. operator= is not defined explicitly. Does c++ default to the copy constructor (which exists)? I don't know. It's not clear to me. I could go back and reread c++ or ask an ai but I will probably quickly forget. To me it would be better if operator= was explicitly defined. Or if we just didn't use operator = for wavefronts. |
|
Sigh. Understanding what operator = does is fundamental to C++ . Go learn it. but to begin with A copy constructor in C++ is called whenever a new object is initialized from an existing object of the same class. Key Scenarios Initialization: When a new object is created and explicitly initialized with an existing object (MyClass obj2 = obj1; or MyClass obj2(obj1);). Pass-by-value: When an argument is passed to a function by value. Return-by-value: When a function returns an object by value (though compiler optimizations like Return Value Optimization (RVO) may sometimes omit this). Exception handling: When an exception object is thrown or caught by value. |
|
I actually looked it up right after I posted. |
|
Yes it is complex but important to remember when writing complex classes. Too long ago for me to remember all the ins and outs of why I did what I did on the wave front. It works and I hate to change any of it's logic. If it is only comments then ok. If it is code then I don't have time to test it and can not be relied on to approve if it is not addressing any known bug. |
|
OK I made the commit. To clarify again, previously the copy operator and the copy constructor did not do the same job. I'm not aguing about the necessity of shallow or deep copy. Current code works fine and I did not find any flaw (I spent quite some time to find one). Deep and shallow copy are correctly used on purpose. What I did in last commit is just explicit the deep VS shallow copy. I did not change behavior of the code. I think this helps maintainability and readability but I let you owner of final decision. PS: When using a shallow copy, one shall not modify any matrix before creating a new one really owned by wavefront or you will modify data from a different wavefront. |
|
🚀 New build available for commit |
|
Ok build fails because of weaker copy elision in C++14. this code would require C++17 to compile. |
|
But it sounds like Dale wants option 3. |
|
I don't like option 3. It's confusing that copies some things and copies more things. |
|
OK, I understand. That is good. Sorry I was too busy to understand exactly. I just looked at wavefront.cpp and realized that it is very sparse. Go ahead with the comment modifications. |
|
I'm sorry i was too busy to understand before. yes go ahead with any of the options you guys think is best. I had not understood that atjsu had added copy operations to wavefront years ago. In fact I just needed one in my live video processing. Thanks atjsu. Sorry for my confusion. |
|
In addition I get a clang warning about padding being excessive that I did not understand. AI explained it to me. If we reorder the variables in the class so that the all the doubles are after all the larger things like mats and then all the bools are after the doubles then padding is optimized and the class takes up less room. So now I'm recommending that be done as well. |
|
🚀 New build available for commit |
See issue #62 for details.
I only cleaned the manual destructor and added init for some missing fields of constructor.
I decided to not do a deep copy inside move constructor because it could have performance impact. I'm supposing Dale did it like this on purpose.
Cleaner solution would be to create explicit functions "deepCopy" and "lightCopy" but as it works I prefer not to touch.
code is documented so just be careful
consider this close #62