1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/// # 借用与引用
///
/// Base usage: 为函数传递数组,使用可变绑定作为参数
///    因为传入的是不可变,而经过函数参数的模式匹配,成为了可变参数
/// ```rust
/// fn foo(mut v: [i32; 3]) -> [i32; 3] {
///     v[0] = 3;
///     assert_eq!([3,2,3], v);
///     v
/// }
/// fn main() {
///     let v = [1,2,3];
///     foo(v);
///     assert_eq!([1,2,3], v);
/// }
/// ```
///
/// Base usage: 以可变引用作为参数
///
/// ```rust
/// fn foo(v: &mut [i32; 3]) {
///     v[0] = 3;
/// }
/// fn main() {
///     let mut v = [1,2,3];
///     foo(&mut v);
///     assert_eq!([3,2,3], v);
/// }
/// ```
pub fn borrow(){
    fn foo(mut v: [i32; 3]) -> [i32; 3] {
        v[0] = 3;
        assert_eq!([3,2,3], v);
        v
    }
    fn main() {
        let v = [1,2,3];
        foo(v);
        assert_eq!([1,2,3], v);
    }

}

/// # 借用与引用
///
/// Base usage: 冒泡排序
///
/// ```rust
/// fn bubble_sort(a: &mut Vec<i32>) {
///     let mut n = a.len(); // 获取数组长度
///     while n > 0 {
///         // 初始化遍历游标,max_ptr始终指向最大值
///         let (mut i, mut max_ptr) = (1, 0);
///         // 冒泡开始,如果前者大于后者则互换位置,并设置当前最大值游标
///         while i < n {
///             if a[i-1] > a[i] {
///                 a.swap(i-1, i);
///                 max_ptr = i;
///             }
///             i += 1;
///         }
///         // 本次遍历的最大值位置即是下一轮冒泡的终点
///         n = max_ptr;
///     }
/// }
/// fn main() {
///     let mut a = vec![1, 4, 5, 3, 2];
///     bubble_sort(&mut a);
///     println!("{:?}", a); // [1, 2, 3, 4, 5]
/// }
/// ```
pub fn bubble_sort_demo(){
    fn bubble_sort(a: &mut Vec<i32>) {
        let mut n = a.len(); // 获取数组长度
        while n > 0 {
            // 初始化遍历游标,max_ptr始终指向最大值
            let (mut i, mut max_ptr) = (1, 0);
            // 冒泡开始,如果前者大于后者则互换位置,并设置当前最大值游标
            while i < n {
                if a[i-1] > a[i] {
                    a.swap(i-1, i);
                    max_ptr = i;
                }
                i += 1;
            }
            // 本次遍历的最大值位置即是下一轮冒泡的终点
            n = max_ptr;
        }
    }
    fn main() {
        let mut a = vec![1, 4, 5, 3, 2];
        bubble_sort(&mut a);
        println!("{:?}", a); // [1, 2, 3, 4, 5]
    }

}

/// # 借用检查
///
/// Base usage: 借用检查保证了内存安全
///    试想,input 和 output 如果将同一个变量的 不可变和可变引用同时传入会发生什么?
///
/// ```rust
/// fn compute(input: &u32, output: &mut u32) {
///     if *input > 10 {
///         *output = 1;
///     }
///     if *input > 5 {
///         *output *= 2;
///     }
/// }
/// fn main() {
///     let i = 20;
///     let mut o = 5;
///     compute(&i, &mut o); // o = 2
///  // let mut i = 20;
///  // compute(&i, &mut i);  // 借用检查不会允许该行编译成功

/// }
/// ```
///
/// Base usage: 优化该函数
/// ```
/// fn compute(input: &u32, output: &mut u32) {
///     let cached_input = *input;
///     if cached_input > 10 {
///         *output = 2;
///     } else if cached_input > 5 {
///         *output *= 2;
///     }
/// }
/// fn main() {
///    let i = 20;
///    let mut o = 5;
///    compute(&i, &mut o); // o = 2
/// }
/// ```
pub fn borrow_check(){
    fn compute(input: &u32, output: &mut u32) {
        if *input > 10 {
            *output = 1;
        }
        if *input > 5 {
            *output *= 2;
        }
    }
    fn main() {
        let i = 20;
        let mut o = 5;
        compute(&i, &mut o); // o = 2
    }

}

/// # 解引用操作将获得所有权
///
/// Base usage: 解引用移动语义类型需要注意
///
/// ```rust
/// fn join(s: &String) -> String {
///     let append = *s;
///     "Hello".to_string() + &append
/// }
/// fn main(){
///     let x = " hello".to_string();
///     join(&x);
/// }
/// ```
pub fn deref_move_type(){
    // fn join(s: &String) -> String {
    //     let append = *s;
    //     "Hello".to_string() + &append
    // }
    // fn main(){
    //     let x = " hello".to_string();
    //     join(&x);
    // }
}