The following code results in SIGSEGV and I cannot understand why is that.
#include <iostream>
using namespace std;
struct C {
C(int x) { ptr = new int(x); }
C(C&& c) { ptr = c.ptr; c.ptr = nullptr; }
int* ptr;
};
void foo(int* x, C c) {
cout << *x << endl;
}
int main() {
C c(10);
foo(c.ptr, std::move(c));
return 0;
}
I would expect the pointer c.ptr to be passed by value to the function foo, however it behaves like its passed by reference.
Now, if I change the ordering of arguments: void foo(C c, int* x), than the problem disappears. The other solution is to create a local copy of c.ptr before calling to x, and than passing that local copy to foo.
I would like to understand why can't i pass c.ptr by value in the sample code above.
It is passed by value, however:
foo(c.ptr, std::move(c));
It is unspecified in which order the parameters that are passed to a function call get evaluated.
Order of evaluation of the operands of almost all C++ operators (including the order of evaluation of function arguments in a function-call expression ... ) is unspecified.
"Unspecified" means that they can be evaluated in any order. The order can even be different each time you run the program. Your compiler chose to generate code that evaluates the 2nd parameter with the std::move
first. As such, your move constructor moves the pointer out of the object, setting it to null. Then, c.ptr
gets evaluated, passing the now-null pointer by value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With