프로그래밍백엔드 개발자

러스트에서 상수 문자열과 동적 문자열(String, &str)을 사용하는 특별한 점은 무엇인가요? 사용 및 변환 시 어떤 어려움이 있나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

문제의 역사

러스트에는 두 가지 주요 문자열 유형이 있습니다 — &str (슬라이스 문자열, 변경 불가능하며, 일반적으로 문자열 리터럴)과 String (동적이고, 변경 가능한 문자열). 언어 개발 초기 단계에서 이들 간의 선택은 효율적인 메모리 작업을 단순화하고 텍스트 데이터를 처리할 때 타입 안전성을 제공할 수 있게 했습니다. 이는 소유권과 참조의 엄격한 시스템 덕분입니다.

문제

많은 개발자들이 이 두 타입 간의 상호작용에 혼란을 겪습니다. 예를 들어, 문자열 리터럴은 &'static str, 즉 컴파일 시에 할당된 불변 문자열에 대한 참조인 반면, String은 동적으로 확장되며 런타임 시에 얻은 데이터를 포함할 수 있습니다. 따라서 이들 타입 간의 변환 방법, 소유권을 올바르게 사용하는 방법 및 불필요한 복사를 피하는 방법에 대한 질문이 종종 발생합니다.

해결책

&strString 간의 변환은 소유권의 기본 규칙을 이해하면 투명합니다:

  • String에서 슬라이스를 얻으려면 참조(my_string.as_str()) 또는 단순 대여(&my_string)를 사용하면 됩니다.
  • &strString으로 변환하려면 to_string() 또는 String::from()을 사용합니다.
  • 소유권과 가변성이 문자열을 수정할 수 있는지 또는 복제가 필요한지를 결정합니다.

코드 예:

fn main() { let s_literal: &str = "hello"; let s_string: String = String::from(s_literal); let s_slice: &str = &s_string; let new_string = s_slice.to_string(); println!("{} {}", s_string, new_string); }

주요 특징:

  • &str은 힙 메모리를 차지하지 않으며 항상 변경 불가능합니다.
  • String은 동적으로 메모리를 할당할 수 있으며 변경 가능합니다.
  • 소유권 및 참조를 정확히 이해하면 간단한 변환이 가능합니다.

미묘한 질문들.

러스트에서 문자열 리터럴을 수정할 수 있나요?

아니요, 문자열 리터럴(&'static str)은 항상 변경 불가능하며, 문자를 수정하려는 시도는 컴파일 단계에서 오류를 발생시킵니다.

&str에서 .to_string()을 호출하는 것으로 불필요한 복사 없이 변경 가능한 문자열을 얻을 수 있나요?

아니요, .to_string()은 항상 새로운 메모리를 할당하고 내용을 복사합니다. 이는 슬라이스 기반의 변경 가능한 문자열이 필요할 때 피할 수 없는 일입니다.

String에서 &str 참조를 생명 주기 오염 없이 얻을 수 있나요?

네, 이렇게 얻은 참조(let s: &str = &my_string;)는 원래의 String보다 오래 살지 않습니다. 함수에서 로컬 String에서 &str을 반환하려고 하면 생명 주기 오류가 발생합니다.

일반적인 오류 및 안티 패턴

  • 범위를 벗어나는 임시 String에 대한 &str 참조를 보존
  • 불필요하게 매번 &strString으로 변환 (불필요한 할당 발생)
  • String::from("text")가 데이터 복사를 생성하지 않을 것이라고 기대

실제 사례

부정적 사례

함수가 함수 내의 임시 String에 대한 &str 참조를 반환합니다:

fn faulty() -> &str { let s = String::from("Oops"); &s // 생명 주기 오류! }

장점:

  • 단순해 보인다

단점:

  • 컴파일되지 않으며 생명 주기 규칙을 위반
  • 이미 파괴된 메모리에 대한 참조 유출 가능성

긍정적 사례

함수가 즉시 String을 반환하고 호출자에게 소유권을 전달합니다:

fn correct() -> String { String::from("Safe!") }

장점:

  • 생명 주기 문제 없음
  • 코드가 신뢰할 수 있음

단점:

  • 문자열이 크고 그에 대한 소유권이 필요하지 않은 경우 참조를 전달하는 것보다 메모리 비용이 더 클 수 있음