알아!?Rust의 소유권 시스템
소유권은 자원을 개방하는 권리를 가리킨다
소유권은 함수로 자원을 개방할 권리다.가졌다기보다는 소비된 이미지에 가깝다.
다음은 변수의 속박에 대한 해설이 많은데 아마도 걸려 넘어진 것은 함수일 것이다.
let a = String::from("abc");
let b = a;
println!("{}", a); // bに所有権が移動するのでコンパイルエラー
let c: u32 = 1;
let d: u32 = c;
println!("c = {}, d = {}", c, d); // 基本データ型はCopyトレイトを実装しているのでコンパイル可能
, 지금부터 함수의 예로 설명하자면...다음 함수
foo
는 b: Bar
에 속한다.함수가 끝났을 때b
가 이미 가지고 있기 때문에 버려집니다(Drop).함수가 끝났을 때b
가 없으면 버려지지 않습니다(나중에 자세히 설명합니다).fn foo(b: Bar) {
/* 直接的にbを所有して利用 */
} // この関数がbの所有権を持っているのでDropされる
let a = Bar::new();
foo(a);
// a は fooに所有されてしまうので、使えなくなる
이 자원의 소유권은 여러 곳에서 소유할 수 없다.소유자가 마지막으로 그 자원을 개방했기 때문에 항상 한 곳이다.이것을 위반하는 코드를 썼으면 컴파일할 수 없습니다.소유권의 이동
소유권을 빼앗은 후 다른 함수에 소유권을 양도하면 어떻게 될까.다음 예에서 소유권이
self.bar_list.push
foo
로 이전되었기 때문에 폐기되지 않는다.이런 소유권 이동을 이동이라고 부른다.참고로 실체형을 정의했지만 복사 비용도 필요 없다.이동 중에는 복제가 발생하지 않습니다.fn foo(&mut self, b: Bar) {
self.bar_list.push(b); // ムーブ
} // この関数がbの所有権を持っていないのでDropしない
폐기된 시간은 변하지만 소유권은 박탈되지 않는다.let a = Bar::new();
x.foo(a); // ムーブ
// a は fooに所有(消費)されてしまうので、使えなくなる
어디서 폐기됐는지 일일이 설명하지만 실제 코드를 쓸 때는 개의치 않는다.그건 b
에 맡겨야 하니까.참고로 파동이 발생하는 조작은 다음과 같다(실천 Rust 입문 참조).
rustc
표현식 뿐만 아니라 match
문장 변수의 제약도 포함)let
클론소유권의 대여
어떤 자원의 소유권 함수를 호출한 후, 이 자원을 이용하려면 복사본을 제출하는 것 외에, 이 함수의 반환값으로만 자원의 소유권을 되돌려받을 수 있습니다.불편하다
fn foo(b: Bar) -> Bar {
// ...
b // 関数からのリターンで所有権をムーブできる
}
let a = Bar::new();
let a = foo(a.clone()); // 複製をムーブする
println!("{:?}", a);
이럴 때 사용하는 것은 참고용 차용이다.매개변수 유형은 참조입니다.빌려썼으면 그 이름대로 폐기되지 않았을 텐데.그 함수는 자원이 없기 때문이다.fn foo(b: &Bar) {
/* bを借用して利用 */
} // 参照のbはDropされない
let a = Bar::new();
foo(&a); // 借用
println!("{:?}", a);
은 대여(참조)를 사용하는 일반적인 예로 멤버의 참조를 반환하는 경우입니다.pub fn name(&self) -> &str {
&self.name
}
이동(이동)/대여(폴로)의 불량 예
다음 공식 문서는 참조가 될 수 있습니다.보충하면서 생각하다.
인용을 받아들이지만 함수 내부에서 특별히 복제한 예
파라미터 소유권이 필요한 함수는 차용 복제가 아니라 소유권을 받아들여야 한다.
// 良い例:
fn foo(b: Bar) {
/* 直接的にbを所有して利用 */
} // この関数がbの所有権を持っているのでDropされる
// 悪い例:
fn foo(b: &Bar) {
let b = b.clone(); // わざわざcloneする…。
/* 複製後にbを所有して利用 */
} // 複製されたbがDropされるが、参照のbは借用なのでDropされない
나쁜 예는 상당히 자유롭지만 무의미한move
을 하기보다는 처음부터 소유권을 박탈하는 것이 좋다.흔들리면 곤란해진다면 다음과 같다clone
.나쁜 예와 무엇이 다르다면 호출자는 복제의 결정권을 가지고 디자인에 유연성을 가진다.let a = Bar::new();
foo(a.clone()); // 呼び出し元が複製を作るかを決める
println!("{:?}", a);
소유권을 빼앗지만 함수 내부에서 소유권을 이용하지 않는 예
함수에 매개 변수의 소유권이 필요하지 않으면, 최종drop이 아닌 가변 또는 비가변 차용을 받아야 한다.
// 良い例:
fn foo(b: &Bar) {
/* bを借用して利用 */
} // 参照のbはDropされない
// 悪い例:
fn foo(b: Bar) {
/* 実質的にbは所有されず借用のみ。関数の最後にDropされる */
} // この関数がbの所有権を持っているのでDropされる
어떤 사인이 좋을까요?
상기에서 말한 바와 같이
clone
의 구성원 중self
과 같은 구성원은 이 값을 읽는 상황, 쓴 상황에서 어떤 서명이 좋은지 간단하게 요약할 것이다.값을 보다
※ T는 모든 종류
name: Name
) -> &self
pub fn name(&self) -> &Name {
&self.name
}
&T
) -> &self
T
는 지연되어야 한다.정말 복제품을 원하십니까? 호출자에 따라 판단하고 싶습니다.pub fn name(&self) -> Name {
self.name.clone() // 実体が必要かどうかわからない状況で 先に複製を作る…
}
clone
) -> self
&T
의 소유권을 빼앗았기 때문에 이 방법의 마지막에 폐기되었다.물론 self
도 폐기된다.이 name
의 인용을 되돌릴 수 없어서 컴파일 오류가 발생했습니다.pub fn name(self) -> &Name {
&self.name // コンパイルできない
} // selfがDropされる
name
) -> self
T
는 폐기되지만 self
는 이동된다.나머지name
만 남기고 나머지는 버린 셈이다.이름만 읽고 싶은데 name
찢어지는 건 불편한 것 같아요.pub fn name(self) -> Name {
self.name // nameだけムーブする
} // selfがDropされる
이 모델은 언제 쉽게 사용할 수 있는지 말하려면self
에서 다른 실례가 생겼을 때 사용할 수 있다.예를 들어 구축기의build 방법 등입니다.pub fn build(self) -> Request {
Request::new(self.name, self.group_id)
}
self
에서 받아들인 후 직접 아무 일도 하지 않으면 폐기된다.따라서 일반적으로 읽기보다는 self
에서 다른 값으로 전환하는 것이 좋다.값을 매기다
함수 내부에 모음에 추가하거나 구성원을 대입할 때 소유권을 가져야 합니다.
self
, &mut self
) &T
.처음부터 소유권을 빼앗는 게 좋을 거야.pub fn add_name(&mut self, name: &Name) {
self.names.push(name.clone());
}
clone
, &mut self
) pub fn add_name(&mut self, name: Name) {
self.names.push(name);
}
구조 구성원이 T
이 있다면 실례를 만드는 공장 함수를 사용하여 소유권을 빼앗아야 한다.pub fn new(name: Name) -> Person {
Person {
name
}
}
Name
, mut self
) &T
되돌아오는 값을 되돌려주지 않으면 버림mut self
만 된다.거의 무의미하다.pub fn add_name(mut self, name: &Name) {
self.names.push(name.clone());
} // selfがDropされる…
self
, mut self
) pub fn add_name(mut self, name: Name) {
self.names.push(name);
} // selfがDropされる…
T
의 경우도 변환의 용례가 되겠죠.가변 참조할 때만 부르고 싶다면
mut self
이 되지만 build0
처럼 내부에서 가변할 수 있다.pub fn build0(mut self) -> Request {
self.name = "(" + self.name + ")";
Request::new(self.name, self.group_id)
}
pub fn build1(self) -> Request {
let mut temp = self;
temp.name = "(" + self.name + ")";
Request::new(self.name, self.group_id)
}
총결산하면 대체로 도안이 형성된다.Rust의 경우 금형에 대한 정보가 많아 서명만 봐도 내부에서 무슨 일이 일어날지 알 수 있다.읽기
build1
->&self
pub fn name(&self) -> &Name {
&self.name
}
쓰기 &T
, &mut self
pub fn add_name(&mut self, name: Name) {
self.names.push(name);
}
공장 상황 쓰기pub fn new(name: Name) -> Person {
Person {
name
}
}
T
에서 무엇으로 전환되는 경우pub fn build(self) -> Request {
Request::new(self.name, self.group_id)
}
Reference
이 문제에 관하여(알아!?Rust의 소유권 시스템), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/j5ik2o/articles/918c54411d5a61텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)