문자열을 & 'static str로 변환하는 방법


91

어떻게 변환 할 String&str? 보다 구체적으로는, 내가로 변환하고 싶은 strstatic수명 ( &'static str).


그것은 가능하거나 바람직하지 않은 것 같습니다. 'static수명은 문자열이 할당 해제되지 않음을 의미합니다. 즉, 메모리 누수입니다. 적절한 &'static str대신 왜 필요 합니까? &'a str'a

3
그것을 &'a str 그때 로 변환하는 것은 어떻게 보 일까요?
Christoph

을 통해 as_slice. 해결하려는 구체적인 문제와 해결하는 동안 발생하는 문제를 설명하면 도움이 더 쉬울 것입니다.

또한 SendStr소유 된 문자열 또는 정적 문자열 인 유형에 유의하십시오 .
Chris Morgan

답변:


134

Rust 1.0 업데이트

s는 프로그램의 전체 수명 동안 살 수 없기 때문에 &'static stra에서 얻을 수 없습니다 . 그것이 평생의 의미입니다. 자신의 수명에 따라 매개 변수화 된 슬라이스 만 가져올 수 있습니다 .StringString&'staticString

Stringa에서 슬라이스 로 이동하려면 &'a str슬라이스 구문을 사용할 수 있습니다.

let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..];  // take a full slice of the string

또는 명시 적 재차 용 을 String구현 Deref<Target=str>하고 수행하는 사실을 사용할 수 있습니다 .

let s_slice: &str = &*s;  // s  : String 
                          // *s : str (via Deref<Target=str>)
                          // &*s: &str

훨씬 더 간결한 구문을 허용하는 또 다른 방법도 있지만 컴파일러가 원하는 대상 유형을 결정할 수있는 경우에만 사용할 수 있습니다 (예 : 함수 인수 또는 명시 적으로 유형이 지정된 변수 바인딩). deref coercion 이라고하며 &연산자 만 사용할 수 있으며 컴파일러는 *컨텍스트에 따라 적절한 양의 s를 자동으로 삽입합니다 .

let s_slice: &str = &s;  // okay

fn take_name(name: &str) { ... }
take_name(&s);           // okay as well

let not_correct = &s;    // this will give &String, not &str,
                         // because the compiler does not know
                         // that you want a &str

이 패턴은 String/에 대해 고유하지 않습니다. 예를 들어 / 및 / 에서 모듈 또는 / 에서 모듈을 &str통해 연결된 모든 유형 쌍에 사용할 수 있습니다 .DerefCStringCStrOsStringOsStrstd::ffiPathBufPathstd::path


29
Rust 1.10에서는 다음과 let s_slice: &str = &s[..];같이 간단하게 수행 할 수 있습니다.let s_slice: &str = s.as_str();
Shnatsel

3
때때로, 원래 문자열은 match {...} 블록 에서처럼 충분히 살지 않습니다. 그러면 's' does not live long enough error.
Dereckson 2011

41

당신은 그것을 할 수 있지만, 포함 의 메모리를 누출String . 이것은 당신이 가볍게해야 할 일이 아닙니다. 의 메모리를 누수함으로써 String메모리가 해제되지 않을 것임을 보증합니다 (따라서 누수). 따라서 내부 개체에 대한 모든 참조는 'static수명 이있는 것으로 해석 될 수 있습니다 .

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let s: &'static str = string_to_static_str(s);
}

8
String객체가 삭제되지 않는 한 메모리가 살아남는 것을 보장합니다. 때문에 mem::forget객체가 하락하지 않을 것이라는 점을 보장, 우리는 포함에 대한 참조가 보장되어 str무효로하지 않습니다. 따라서 우리는 그것이 'static참조 라고 주장 할 수 있습니다
oli_obk

1
이것은 강요하는 데 필요한 내 녹 응용 프로그램을위한 매우 도움이되었다 String&'static str원본에서 만든 토큰 있도록 String모든 스레드에서 사용할 수있을 것이다. 이것이 없으면 Rust 컴파일러는 내 String수명이 주 함수의 끝에서 끝났다고 불평 할 것 'static입니다. 보증 이 없기 때문에 충분하지 않았습니다 .
mmstick

1
@mmstick :이 경우에 더 나은 솔루션을 사용하는 것입니다 crossbeam스레드 및 범위
oli_obk

3
@mmstick : 전체 애플리케이션을 크로스 빔 범위에 넣고 범위 외부에 문자열을 생성하면 정확히 얻을 수 있습니다.
oli_obk

1
이 대답은 훌륭합니다! 둘 다 정적 인 문자열 슬라이스를 교활하게 만드는 방법을 알려주고 그렇게하지 않도록 설득했습니다! 나는 많은 곳에서 정적 문자열 조각을 사용하지 않도록 내 앱을 리팩토링하기로 결정했습니다.
Paul Chernoch

22

Rust 버전 1.26부터는 코드 를 사용하지 않고도 a String를 로 변환 할 수 있습니다.&'static strunsafe

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

이것은 String인스턴스를 박스형으로 변환 str하고 즉시 누출합니다. 이렇게하면 문자열이 현재 차지할 수있는 모든 초과 용량이 해제됩니다.

거의 항상 누수 객체보다 선호되는 솔루션이 있습니다. 예를 들어 crossbeam스레드간에 상태를 공유하려는 경우 상자를 사용합니다 .


2

TL; DR : 당신은 그 자체가 평생을 가지고있는 a &'static str로부터 얻을 수 있습니다 .String'static

다른 답변이 정확하고 가장 유용하지만 실제로 a String를 a 로 변환 할 수있는 (그다지 유용하지 않은) 엣지 케이스가 있습니다 &'static str.

참조의 수명은 항상 참조 된 개체의 수명보다 짧거나 같아야합니다. 즉, 참조 된 객체는 참조보다 오래 (또는 동일하게) 살아야합니다. 'static프로그램의 전체 수명을 의미 하므로 더 긴 수명은 존재하지 않습니다. 그러나 동등한 수명이면 충분합니다. 따라서 Stringa의 수명이 'static이면 &'static str참조를 얻을 수 있습니다 .

이론적 static으로 유형 생성 Stringconst fn기능이 출시 되었을 때 Rust 1.31에서 가능해 졌습니다. 불행히도 a를 반환하는 유일한 const 함수 StringString::new()현재이며 여전히 기능 게이트 뒤에 있습니다 (따라서 지금은 Rust nightly가 필요합니다).

따라서 다음 코드는 원하는 변환을 수행합니다 (야간 사용) ... 실제로이 엣지 케이스에서 가능하다는 것을 보여주는 완성도를 제외하고는 실용적이지 않습니다.

#![feature(const_string_new)]

static MY_STRING: String = String::new();

fn do_something(_: &'static str) {
    // ...
}

fn main() {
    do_something(&MY_STRING);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.