为什么将std :: move(object)和此对象的成员传递给函数会导致SIGSEGV

Buy*_*yuk 4 c++ move operator-precedence segmentation-fault

以下代码导致SIGSEGV,我无法理解为什么会这样.

#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;
}
Run Code Online (Sandbox Code Playgroud)

我希望指针c.ptr可以通过值传递给函数foo,但它的行为类似于它通过引用传递.

现在,如果我更改参数的顺序:void foo(C c,int*x),问题就会消失.另一个解决方案是在调用x之前创建c.ptr的本地副本,而不是将该本地副本传递给foo.

我想了解为什么我不能在上面的示例代码中通过值传递c.ptr.

Sam*_*hik 6

它按值传递,但是:

foo(c.ptr, std::move(c));
Run Code Online (Sandbox Code Playgroud)

未指定以何种顺序传递传递给函数调用的参数.

几乎所有C++运算符的操作数的评估顺序(包括函数调用表达式中函数参数的评估顺序......)都未指定.

"未指定"表示可以按任何顺序评估它们.每次运行程序时,订单甚至可以不同.您的编译器选择生成用第std::move一个参数计算第二个参数的代码.因此,您的移动构造函数将指针移出对象,将其设置为null.然后,c.ptr进行评估,按值传递now-null指针.

  • @Buyuk你不能强制评估功能参数的顺序. (3认同)