시작에서 피트까지 Rust 언어 - (5) Rust 소유권


여기에 이미지 설명 삽입

0 수입

주로 Rust 소유권에 대한 지식을 소개하며 변수의 범위, 메모리 해제 메커니즘, 이동, 복제, 참조 및 기타 지식을 포함하며 많은 지식은 Rust 언어의 고유한 메커니즘입니다.


1. 소유권

소유권에는 다음 세 가지 규칙이 있습니다.

- Rust의 모든 값에는 소유자라는 변수가 있습니다.
- 한 번에 한 명의 소유자만 있을 수 있습니다.
- 소유자가 프로그램 범위에 없으면 값이 삭제됩니다.

{
    
    
    // 在声明以前,变量 s 无效
    let s = "runoob";
    // 这里是变量 s 的可用范围
}
// 变量范围已经结束,变量 s 无效

2. 메모리 및 할당

대부분의 프로그래밍 언어에는 메모리 관리 기능이 있습니다.

1. C/C++ 등의 언어는 주로 수동으로 메모리를 관리하며, 개발자는 메모리 리소스를 수동으로 신청하고 해제해야 합니다. 그러나 개발 효율성을 높이기 위해 프로그램 기능 구현에 영향을 미치지 않는 한 많은 개발자는 메모리를 제때 해제하는 습관을 갖지 않습니다. 따라서 수동으로 메모리를 관리하는 방식은 자원 낭비로 이어지는 경우가 많고, 메모리 해제를 잊어버리기 쉬워 메모리 누수가 발생한다.
2. Java 언어로 작성된 프로그램은 가상 머신(JVM)에서 실행되며 JVM은 자동으로 메모리 자원을 회수하는 기능을 가지고 있습니다. 그러나 이 방법은 종종 런타임 효율성을 감소시키므로 JVM은 가능한 적은 리소스를 회수하므로 프로그램이 많은 메모리 리소스를 차지하게 됩니다.
3. 소유권은 대부분의 개발자에게 생소한 개념으로 메모리를 효율적으로 사용하기 위해 Rust 언어로 설계된 구문 메커니즘입니다. 소유권 개념은 Rust가 컴파일 단계에서 메모리 자원의 유용성을 보다 효과적으로 분석하여 메모리 관리를 달성할 수 있도록 하기 위해 탄생한 개념입니다.
4. 소유권 설정이 이상해 보입니다.사실 같은 변수 데이터가 여러 변수 참조를 가지는 것은 언어 수준에서 본질적으로 금지되어 있습니다.매개 변수로 전달되면 소유권이 이동(Move)됩니다.또는 차용 (빌리다). 다른 변형에 할당하면 자동으로 소유권이 포기됩니다. 동시 시나리오에서 데이터 공유 충돌을 근본적으로 제거합니다.
5. Rust 데이터 유형은 기본 데이터 유형과 기타 가변 데이터 유형(String과 같은 가변 길이)으로 나눌 수 있습니다.
기본 데이터 유형에는
i32, u32, i64 등과 같은 모든 정수 유형이 포함됩니다
. 값은 true 또는 false
모든 부동 소수점 유형, f32 및 f64
문자 유형 char
위 유형의 데이터를 포함하는 튜플(Tuples)만

기본 데이터는 일반적으로 스택에 정의되고 나머지는 힙에 정의됩니다. 소유권을 잃을 때마다 Rust가 자동으로 해제하는 data?


3. 이동 및 복제

3.1 모바일

다음 코드:

    //基本数据在栈中定义,交互数据是直接复制的,通过移动复制
    let x = 5;
    let y = x;
    println!("{}, {}",x,y);

	//其他数据在堆中交互
	let s1 = String::from("hello");
	let s2 = s1;                // 为了确保安全,在给 s2 赋值时 s1 已经无效了
	println!("{}, world!", s1); // 错误!s1 已经失效

3.2 복제

Rust는 프로그램의 실행 비용을 최대한 줄이려고 하므로 기본적으로 길이가 큰 데이터는 힙에 저장하고 데이터 상호 작용은 이동하여 수행합니다. 그러나 단순히 다른 용도로 데이터를 복사해야 하는 경우 두 번째 대화식 데이터 복제 방법을 사용할 수 있습니다.

    let s1 = String::from("hello");
    let s2 = s1.clone();
    println!("s1 = {}, s2 = {}", s1, s2);

이렇게 하면 두 개의 개별 데이터 세트가 생성됩니다.


4. 견적 및 임대

4.1 인용

참조(Reference)는 C++ 개발자에게 친숙한 개념입니다. 포인터의 개념에 익숙하다면 일종의 포인터라고 생각하시면 됩니다. 본질적으로 "참조"는 변수의 간접 액세스 방법입니다.

fn main() {
    
    
    let s1 = String::from("hello");
    let s2 = &s1;
    println!("s1 is {}, s2 is {}", s1, s2);
}

1. 변수의 값을 참조할 때 변수 자체는 유효하지 않은 것으로 간주하지 않습니다. "참조"는 스택의 변수 값을 복사하지 않기 때문에
2. 참조는 값의 소유권을 얻지 않습니다. 참조는 값의 소유권만 차용(Borrow)할 수 있습니다. 참조 자체도 유형이며 다른 값의 위치를 ​​기록하는 값을 갖지만 참조는 가리키는 값에 대한 소유권이 없습니다.

fn main() {
    
    
    let s1 = String::from("hello");
    let s2 = &s1;
    let s3 = s1;
    println!("{}", s2);
}
//注意 因为 s2 租借的 s1 已经将所有权移动到 s3,所以 s2 将无法继续租借使用 s1 的所有权。如果需要使用 s2 使用该值,必须重新租借,如下

fn main() {
    
    
    let s1 = String::from("hello");
    let mut s2 = &s1;
    let s3 = s1;
    s2 = &s3;        // 重新从 s3 租借所有权
    println!("{}", s2);
}

3. 임대한 소유권은 소유자의 가치를 변경할 수 없으며 참조는 소유권이 없기 때문에 소유권을 임대하더라도 사용권만 향유합니다.
4. 불변 참조와 비교할 때 가변 참조는 다중 참조를 허용하지 않지만 불변 참조는 허용합니다.

fn main() {
    
    
    let s1 = String::from("run");
    let s2 = &s1;
    println!("{}", s2);
    s2.push_str("oob"); // 错误,禁止修改租借的值
    println!("{}", s2);
}
//当然加上 mut表示可变变量时候,是允许修改的
fn main() {
    
    
    let mut s1 = String::from("run");
    // s1 是可变的

    let s2 = &mut s1;
    // s2 是可变的引用

    s2.push_str("oob");
    println!("{}", s2);
}

4.1 참조 걸기

C++에서는 다음과 같습니다. 포인터 개념이 있는 프로그래밍 언어에서 액세스할 수 있는 데이터를 실제로 가리키지 않는 포인터를 나타냅니다(반드시 널 포인터일 필요는 없으며 해제된 리소스일 수도 있음에 유의하십시오. ) , 이는 Rust에서 허용되지 않습니다.
일반적으로 지역 변수는 함수에 정의되어 있고 함수의 반환 값은 참조이며, 이는 지역 변수 참조가 반환되는 경우입니다.

5. 함수의 변수

5.1 파라미터 변수

함수의 변수 해제 메커니즘은 위에서 소개한 것과 동일하므로 다음 사항에 주의하십시오.

fn main() {
    
    
    let s = String::from("hello"); // s 被声明有效
    takes_ownership(s); // s 的值被当作参数传入函数, 所以可以当作 s 已经被移动,从这里开始已经无效
    let x = 5;          // x 被声明有效
    makes_copy(x);      // x 的值被当作参数传入函数
                        // 但 x 是基本类型,依然有效
                        // 在这里依然可以使用 x 却不能使用 s
} // 函数结束, x 无效, 然后是 s. 但 s 已被移动, 所以不用被释放

fn takes_ownership(some_string: String) {
    
     // 一个 String 参数 some_string 传入,有效
    println!("{}", some_string);
} // 函数结束, 参数 some_string 在这里释放

fn makes_copy(some_integer: i32) {
    
    // 一个 i32 参数 some_integer 传入,有效
    println!("{}", some_integer);
} // 函数结束, 参数 some_integer 是基本类型, 无需释放

5.2, 반환값 변수

함수의 반환 값으로 사용된 변수의 소유권은 직접 무효화되지 않고 함수 외부로 이동되어 함수가 호출된 위치로 반환됩니다.

fn main() {
    
    
    let s1 = gives_ownership(); // gives_ownership 移动它的返回值到 s1
    let s2 = String::from("hello"); // s2 被声明有效
    let s3 = takes_and_gives_back(s2);// s2 被当作参数移动, s3 获得返回值所有权
} // s3 无效被释放, s2 被移动, s1 无效被释放.
fn gives_ownership() -> String {
    
    
    let some_string = String::from("hello"); // some_string 被声明有效
    return some_string; // some_string 被当作返回值移动出函数
}
fn takes_and_gives_back(a_string: String) -> String {
    
     
    // a_string 被声明有效
    a_string  // a_string 被当作返回值移出函数
}

Supongo que te gusta

Origin blog.csdn.net/ljsant/article/details/131349775
Recomendado
Clasificación