2017-12-19 2 views
0
fn func(s: *mut String, a: *mut i32) -> usize { 
    println!("{}", unsafe { *s }); 
    println!("{}", unsafe { *a }); 

    unsafe { (*s).len() } 
} 

fn main() { 
    let mut s = String::from("hello"); 
    let mut a = 10; 

    func(&mut s, &mut a); 
} 

위의 코드는 오류와 함께 실패합니다문자열에 대한 원시 포인터와 i32에 대한 원시 포인터를 역 참조하는 것의 차이점은 무엇입니까?

error[E0507]: cannot move out of dereference of raw pointer 
--> src/main.rs:2:29 
    | 
2 |  println!("{}", unsafe { *s }); 
    |        ^^ cannot move out of dereference of raw pointer 

이 왜 i32에 대한 String하지위한 일이 무엇입니까? 왜 그것이 "이동"을 불평합니까?

+4

* 왜 "이동"을 불평합니까 * - "이동"이 Rust에서 무엇을 의미하는지 모를 경우 아직 원시 포인터를 사용하지 않아야합니다 *. 돌아가서 전체 입문서 [* The Rust Programming Language *] (https://doc.rust-lang.org/book/secondededition/)를 다시 읽으십시오. – Shepmaster

+0

'std :: ptr :: read '원시 문자열 데이터를 복사하지만 쉽게 정의되지 않은 동작이 발생할 수 있습니다. – CodesInChaos

답변

4

Why does it happen for String and not for i32 ?

기본 정수형 (그리고 사실, 많은 다른 종류의) 녹는 the Copy trait를 구현합니다. 그들에는 "복사 의미론"가 있고, "움직임 의미론"가 아니다. 여기에 소유권의 변경은 없습니다 ... 당신은 가치를 복사하고 있습니다. String 특성을 구현하지 않으므로이 바인딩에는 "이동 의미"가 있습니다.

이것은 원시 포인터에 고유하지 않으며 가변성과 관련이 없습니다. This example shows이 불변 참조로 일어날 수 있습니다

fn func(s: &String, a: &i32) { 
    let _x = *s; 
    let _x = *a; 
} 

Why is it complaining of a "move"?

그것은 당신이 unsafe 블록에서 소유권을 이동하려고 시도하고 있기 때문에이 작업을 수행합니다. 이 부분에 신경 쓰지 않는 한 unsafe 블록 안에 "이동"을 포함시켜야하므로 컴파일러만으로도 발을 쏠 수 있습니다. 따라서, 당신은 당신의 코드를 재구성하면 unsafe 블록의이 코드는 컴파일 밖에 이동하지 너무 :

unsafe { 
    println!("{}", *s); 
} 

Here it is running in the playground합니다.

질문에 대한 코멘트에서 Shepmaster의 요점을 다시 반복하려면 ... "이동"이라는 용어가 외국어로 들리면 처음에는 원시 포인터/unsafe 블록을 사용해서는 안되며 그 대신에 뒤로 가야합니다 Rust에 대한 사용 가능한 문서에서 핵심 개념이므로 개념을 이해할 수 있습니다.

+0

그래서 println!()을 호출 할 때 소유권이 이전 되었습니까? 나는 왜 그것이'let x = String :: from ("hello"); println! ("{}", x); println! ("{}", x); '. 나는 왜 두 번째 println!()이 성공했는지 혼란 스럽다. 또한 "안전하지 않은 블록에서 소유권을 이동하려고 시도하기 때문에이 작업을 수행합니다"에 대해 자세히 설명해주십시오. 내 바보 같은 질문을 참아주십시오. – soupybionics

+2

@soupybionics'println!'은 소유권을 얻지 못합니다 [사실, 그것의 인수를 자동 참조합니다]] (https://stackoverflow.com/questions/30450399/does-println-borrow- or-own-the-variable)이지만 값은 블록 내부에서 외부로 이동해야합니다. [안전하지 않은 동일한 문제의 예가 있습니다.] (https://play.rust-lang.org/?gist=4cf04e1a7aadb054bcc3b6ba64aa03fe&version=stable)'{}'블록은'*} 'unsafe' 블록과 마찬가지로 일시적으로 's'상태가됩니다. 'println! ("{}", * s);'가 작동합니다. (하지만'println! ("{}", s)'.) – trentcl

+0

@trentcl, 고마워! 나는 아직도 그것을 따르지 않고있다. 안전하지 않은 것의 차이점은 무엇인가? { * s; } 및 안전하지 않음 { println! ("{}", * s); } – soupybionics

관련 문제