2013-05-20 4 views
3

편집자 주 :이 코드 예는 1.0 이전의 Rust 버전이며 구문 적으로 유효한 Rust 1.0 코드는 아닙니다. 이 코드의 업데이트 된 버전은 서로 다른 오류를 생성하지만 답변에는 여전히 유용한 정보가 포함되어 있습니다. 테스트 문자열을 빌린 포인터의 벡터에, R '수명으로, 빌린 포인터를한다 ", 그리고이 유형의 서명이 의미 내가 생각빌린 참조의 수명과 벡터에 포함 된 빌려준 포인터의 관계는 무엇입니까?

fn test<'r>(xs: &'r [&str]) -> &'r str { 
    return xs[0]; 
} 

:

나는 녹 0.6에서이 코드를 시도 또한 R '수명으로, 문자열로 빌려 포인터를 반환하지만 컴파일러는 말한다.

refs.rs:2:8: 2:12 error: mismatched types: expected `&'r str` but found `&str` (lifetime mismatch) 
refs.rs:2  return xs[0]; 
         ^~~~ 
refs.rs:1:39: 3:1 note: the lifetime &'r as defined on the block at 1:39... 
refs.rs:1 fn test<'r>(xs: &'r [&str]) -> &'r str { 
refs.rs:2  return xs[0]; 
refs.rs:3 } 
refs.rs:1:39: 3:1 note: ...does not necessarily outlive the anonymous lifetime #1 defined on the block at 1:39 
refs.rs:1 fn test<'r>(xs: &'r [&str]) -> &'r str { 
refs.rs:2  return xs[0]; 
refs.rs:3 } 
error: aborting due to previous error 

이 벡터 내에서 포인터가 오래 살 수 있다는 것을 의미하는 것으로 보인다 (읽기 전용) 벡터 자체 이게 가능하니?

컴파일러에게 알릴 필요가있는 몇 가지 추가 주석이 있습니까?

마찬가지로, 소유 포인터의 벡터는 어떻습니까? 예 :

fn test<'r>(xs: &'r [~str]) -> &'r str { 
    return xs[0]; 
} 

다시, 나는 적어도 한 나는 전체 목록을 차용 한대로의 벡터의 요소에 대한 포인터를 빌릴 수 있기를 기대.

fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str] 

계획이었다 : 컨텍스트에 대한

, 내 원래의 문제는 소유 포인터의 목록을 빌린 점의 목록을 확장하려고했던 모든 빌린 포인터를 가진 exended 목록을 작성, 사용 후 확장 목록을 비우고 포함 된 문자열을 포함하여 소유 포인터의 원래 목록을 비 웁니다.

입니다
fn test<'r>(xs: &[&'r str]) ->  &'r str { 
     return xs[0]; 
} 

, 당신은 평생 연구와 문자열로 빌려 포인터를 포함 빌린 배열 포인터를 가지고,이 포인터, 같은 수명 중 하나를 반환 :

답변

4

소유/고유의 문자열 test의 두 번째 버전은, 일, 바로 컴파일러는이 ~str&'r str A를 변환하기 위해 지원되어야한다 않습니다 ~str이 포함되어 있기 때문에 컴파일러는 수명이 적어도 벡터의 수명이라는 것을 알고 있습니다. (이와 같이 빌려서 mutability에주의해야하므로 문자열을 벡터에서 제거 할 수 없습니다.) 유일한 문제는 컴파일러가 xs[0]을 임시로 쉽게 수행 할 수있는 조각으로 압축하도록 설득하는 것입니다.


extend 같은 것을 보일 수 있습니다 : 그것은 그 vec::each(ys) 작품을 보이지만, 버그 아마 인,하지 ys.each 않습니다

fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str] { 
    let mut xs = xs; 
    for vec::each(ys) |s| { 
     let tmp: &'r str = *s; 
     xs.push(tmp) 
    } 
    xs 
} 

(나는 지금 조사하고 있습니다 나는 #6655을 열었) . 당신이 현재 위치에서 벡터를 수정하려면, 일반적인 방법은 벡터에 변경 가능한 참조를 전달하는 것입니다

, 즉 extend(&mut vec, additions)처럼라고

fn extend<'r>(xs: &mut ~[&'r str], ys: &'r [~str]) { 
    for vec::each(ys) |s| { 
     let tmp: &'r str = *s; 
     xs.push(tmp) 
    } 
} 

. 녹 1.19.0 현재

rusti> let a = &[~"a", ~"b", ~"c"]; 
() 
rusti> test(a) 
"a" 
rusti> extend(~["1", "2", "3"], a) 
~["1", "2", "3", "a", "b", "c"] 
3

내가 무엇을 의미하는 것이라고 생각합니다. 벡터 자체의 수명은 부적합합니다.

두 번째 예제는 함수의 입력에서 빌려 가지 않은 빌린 포인터를 반환하기 때문에 작동하지 않습니다. 배열을 빌려 왔고 그 내용은 그렇지 않습니다.

+0

좋아요,하지만 그게 왜 잘못된 것입니까? 벡터가 어떻게 그 안에있는 참조보다 오래 살 수 있었습니까? –

+0

@ThomasLeonard 귀하의 경우에는 벡터에 문자열에 대한 포인터가 포함되어 있습니다. 이것들이 유일한 포인터가 아닌 경우, 문자열은 벡터보다 오래 지속될 수 있습니다. –

+0

@RamonSnir 어떻게 그 반대를 표현할 수 있습니까? 그 결과 포인터가 제공된 벡터 (적어도 훨씬 더 오래)만큼 유효 할 것이라고 말하고 싶습니다. –

0

나는 이것이 당신이 무슨 뜻이라고 생각 : (문자열에 의해 참조 항상 같은)

문자열 특히
fn get1<'r, T>(xs: &'r [T]) -> &'r T { 
    return &xs[0]; 
} 

fn main() { 
    let a = ~[1, 2, 3]; 
    let b = [1, 2, 3]; 
    let c = @[1, 2, 3]; 
    let ax = get1(a); 
    let bx = get1(b); 
    let cx = get1(c); 
    println(fmt!("%d %d %d", *ax, *bx, *cx)); 
} 

, 그것은하지만 값의 벡터도 잘되지 않을 수 있습니다 - 작동 잘 됐네.xs 벡터가 소유

fn test<'r>(xs: &'r [~str]) -> &'r str { 
    let tmp: &'r str = xs[0]; 
    tmp 
} 

이 작동하는 이유는 다음과 같습니다

+0

불행히도 문자열 대신 포인터를 반환하기 위해 서명을 변경하는 것은 문자열에 대한 포인터 목록이 아닌 문자열 목록을 작성하려고하기 때문에 제 경우에는 도움이되지 않습니다. 내가 질문에 왜 이것을하고 싶었는지에 대한 메모를 추가했습니다. –

0

을 (그리고 아마도 녹 1.0) 이후의 original code works as expected :


설명하기

fn test<'r>(xs: &'r [&str]) -> &'r str { 
    xs[0] 
} 

fn main() {} 

owned string version also works after updating the syntax :

fn test<'r>(xs: &'r [String]) -> &'r str { 
    &xs[0] 
} 

fn main() {} 

더 나은 평생 i nference은 (fn test(xs: &[&str]) -> &strfn test(xs: &[String]) -> &str) 기능에 나는이 문제가 컴파일러하는 방법에 아래로 비등하는 느낌이

을 명시 수명을 가질 필요가 없다는 것을 의미 계산 (공동, 콘트라, IN-) 예를 들어 Rust 1.0 이전에이 사례에 대해 정확하게 계산하지 않은 방법. 슬라이스에 참조가 포함되어 있기 때문에 정확하게 식별하면 참조 의 슬라이스보다 오래 있어야합니다. 이 때문에 더 짧은 수명의 문자열 slice를 'r과 일치하도록 반환하는 것이 안전합니다.