代码之家  ›  专栏  ›  技术社区  ›  Buyuk

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

  •  4
  • Buyuk  · 技术社区  · 7 年前

    下面的代码导致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;
    }
    

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

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

    我想理解为什么我不能在上面的示例代码中按值传递c.ptr。

    2 回复  |  直到 7 年前
        1
  •  6
  •   Sam Varshavchik    7 年前

    但是,它是按值传递的:

    foo(c.ptr, std::move(c));
    

    未指定参数的顺序 that are passed to a function call get evaluated .

    几乎所有C++运算符的操作数求值顺序 (包括函数参数在 函数调用表达式…)未指定。

    “未指定”表示可以按任何顺序对其进行评估。每次运行程序时,顺序甚至可能不同。编译器选择生成用 std::move 第一因此,移动构造函数将指针移出对象,并将其设置为null。然后 c.ptr 获取计算值,按值传递现在为null的指针。

        2
  •  3
  •   François Andrieux    7 年前

    当你打电话的时候 foo(c.ptr, std::move(c)); 你不能肯定 c.ptr std::move(c) 将首先进行评估。未指定函数调用中计算的顺序参数。在你的情况下 std::移动(c) 将首先评估,然后离开 c、 ptr公司 nullptr . 那么你会的 cout << *x << endl 试图取消引用 *x 哪里 x 空PTR .