2017-12-15 29 views
4

다음 코드 결과는 SIGSEGV이고 그 이유는 알 수 없습니다.왜이 개체의 std :: move (object) 및 멤버가 함수로 전달되는지 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을 전달할 수없는 이유를 알고 싶습니다.

+0

당신은 임시로 이동 ... – user1810087

답변

6

그것은 그러나 값으로 전달된다 미지정

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

이되는 파라미터 that are passed to a function call get evaluated 주문. (A 함수 호출 식의 함수 인자의 평가 순서 ... 포함) 거의 모든 C++ 사업자 의 피연산자의 평가

주문은 지정되지 않습니다.

"지정되지 않음"은 임의의 순서로 평가 될 수 있음을 의미합니다. 순서는 프로그램을 실행할 때마다 다를 수 있습니다. 컴파일러는 std::move이있는 두 번째 매개 변수를 먼저 평가하는 코드를 생성하기로 결정했습니다. 따라서 이동 생성자는 포인터를 객체 밖으로 이동하여 null로 설정합니다. 그런 다음 c.ptr이 now-null 포인터를 값으로 전달하여 평가됩니다.

+0

임시 개체를 만들지 않고 컴파일러 구현 세부 정보에 의존하지 않을 이동하기 전에 첫 번째 인수를 강제로 평가할 수있는 방법이 있습니까? – Buyuk

+1

@Buyuk 스스로 평가하고 결과를 저장할 수 있습니다. 'int * x = c.ptr; –

+0

@ FrançoisAndrieux 알아,하지만 때로는 비쌀 수 있기 때문에 임시 개체 (이 경우 포인터)를 만들지 않고 그것을 할 수있는 방법이 있는지 궁금합니다. – Buyuk

3

foo(c.ptr, std::move(c));으로 전화하면 c.ptr 또는 std::move(c)이 먼저 평가됩니다. 함수 호출이 지정되지 않은 경우 순서 인수가 계산됩니다. 귀하의 경우 std::move(c)이 먼저 평가되며 c.ptrnullptr으로 남습니다. 그런 다음 cout << *x << endl을 참조하여 *x을 역 참조하려고 시도합니다. 여기서 xnullptr입니다.