+ 3

Copying a std::function object to another std::function

I have the following declaration of a binary search tree: template<class Type, class Predicate = std::less<Type>> binary_search_tree; In this class, along with a root node, I store a std::function object to be used as the comparison predicate during insert operations. I now had to make a function to generate the mirror image of a binary_search_tree object. In the function implemented for the same, after performing the required operations, I assign a new comparison predicate to the mirrored object: mirror_bst.compare = [this](value_type v1, value_type v2)->bool{ return !this->compare(v1,v2); }; Now, when I try to copy the returned object to a newly created object, the program crashes. Backtracing in GDB shows a SIGSEGV raised in the following call: 0x0000000000404ba0 in std::function<bool (int, int)>::operator()(int, int) const ( __args#1=<optimized out>, __args#0=<optimized out>, this=<optimized out>) The copy constructor is defined in the following way: binary_search_tree(const binary_search_tree& bst) : binary_search_tree() { compare = bst.compare; bst.traverse_preorder([this](const vertex& node){ this->insert(*node); }); } A move constructor is also defined in the class: binary_search_tree(binary_search_tree&& bst) : binary_search_tree() { compare=std::move(bst.compare); root=bst.root; csize=bst.csize; bst.csize=0; bst.root=bst.end_iter; } When the returned object is moved instead of copied, the program works as expected. Why? Also, if the following line: compare = bst.compare; is commented, the program executes successfully but displays incorrect results due to an incorrect predicate. Why does the program not crash in this case? Link to the complete code: https://code.sololearn.com/cDe9SPnEH3T1/#cpp

9th Oct 2019, 3:37 PM
Solo Wanderer 4315
Solo Wanderer 4315 - avatar
4 Answers
+ 2
Deep copy vs Shallow copy issue? Recently studied , have not tried yet. https://owlcation.com/stem/Copy-Constructor-shallow-copy-vs-deep-copy
10th Oct 2019, 7:18 AM
Manual
Manual - avatar
+ 1
*** Thank you very much for your help. I did not look at the complete backtrace and so did not notice the recurrence. However, I am still not able to figure out why the recurrence exists as such, and why it is not observed when I move the returned object into another object (auto bst2 = std::move(bst.mirror)) or comment the line: compare = bst.compare in the copy constructor. Can it be that capturing this has something to do with it?
10th Oct 2019, 2:50 AM
Solo Wanderer 4315
Solo Wanderer 4315 - avatar
+ 1
Manual Thank you for the link. However, as identified by ***, the problem was not with the copying in general, but instead the lambda being called inside the copy assignment operator or the copy constructor. In my copying functions, I reiterate over all the nodes of the tree passed as argument and add new copies of each node to the tree being constructed or assigned. But yes, it might be that the lambda itself is not copied properly, and as a result there is a dangling reference, which might be leading to the infinite recurrence. I am not sure, however.
10th Oct 2019, 7:34 AM
Solo Wanderer 4315
Solo Wanderer 4315 - avatar
0
*** Thank you for the suggestions. I'll try using shared pointers for a solution. For the time being, I'll just try to avoid copying objects and move them instead whenever possible, which is at times a good thing, I suppose.
10th Oct 2019, 6:35 AM
Solo Wanderer 4315
Solo Wanderer 4315 - avatar