以下代码在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。
它是按值传递的,但是:
foo(c.ptr, std::move(c));
未指定的是,将传递给函数调用的参数得到评估。
几乎所有C 操作员的操作数评估顺序 (包括函数参数的评估顺序 函数通话表达式...)未指定。
"未指定"表示可以按任何顺序对其进行评估。每次运行程序时,订单甚至都可能不同。您的编译器选择首先使用std::move
评估第二个参数的代码。因此,您的移动构造函数将指针从对象移出,将其设置为空。然后,对c.ptr
进行评估,按值传递现在无效的指针。
当您致电foo(c.ptr, std::move(c));
时,您不能确保首先评估c.ptr
或std::move(c)
。在函数调用中评估订单参数未指定。在您的情况下,std::move(c)
似乎将首先评估,而c.ptr
则为nullptr
。然后,您进行cout << *x << endl
,试图放置*x
,其中x
为nullptr
。