"首次提交"
This commit is contained in:
1
life_cycle/.gitignore
vendored
Executable file
1
life_cycle/.gitignore
vendored
Executable file
@ -0,0 +1 @@
|
||||
/target
|
8
life_cycle/Cargo.toml
Executable file
8
life_cycle/Cargo.toml
Executable file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "life_cycle"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
83
life_cycle/src/main.rs
Executable file
83
life_cycle/src/main.rs
Executable file
@ -0,0 +1,83 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
life_cycle();
|
||||
}
|
||||
|
||||
fn life_cycle() {
|
||||
{
|
||||
// 这样定义会使得编译器无法识别返回的数据是x还是无法知道返回的这个借用的生命周期是多少,也就无法防止悬垂引用
|
||||
//fn longest(x:&str, y:&str) -> &str {
|
||||
/* 生命周期是泛型参数的一种,可以像使用泛型参数那样使用生命周期,他的语法是单引号+一个小写字母,生命周期标注加在&之后。
|
||||
返回的引用的生命周期是取决于较小生命周期的那个引用的生命周期:
|
||||
如下的例子,x和y的生命周期都是'a, 但是实际传入的x和y的生命周期并不是一样的,所以'a 代表的生命周期是x和y中较小的一个,
|
||||
这样返回的引用的生命周期也就变得是更小的那个,这样无论返回的是x还是y都能够保证有效
|
||||
*/
|
||||
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
||||
if x.len() > y.len() {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
{
|
||||
//test 1
|
||||
let str1 = "str1 ....";
|
||||
let str2 = "str2";
|
||||
let lstr = longest(str1, str2);
|
||||
println!("longest str is {}", lstr);
|
||||
}
|
||||
|
||||
//test 2
|
||||
let str1 = "str1 ....";
|
||||
let lstr;
|
||||
{
|
||||
let t = String::from("str2");
|
||||
/* 如果是一个字符串字面值,那么就没有问题。因为他是static的生命周期 */
|
||||
let str2: &str = "str2";
|
||||
|
||||
/* 如果是一个字符串引用那就不行。因为字符串t会在大括号之后生命结束了,其引用也将失效,
|
||||
而打印语句会在大括号外进行longest的结果打印,那么有可能打印的是这个临时字符串的引用,就会导致悬垂引用,所以编译器就会报错,
|
||||
即使在这个实例中str1才是真正的返回的引用,实际运行并不会崩溃。但是编译器并不知道这个信息。他只从最短的生命周期去评估该代码的风险!
|
||||
通过这种方式迫使你编写必不能导致悬垂引用的代码,因为保不齐那天稍微修改了str1和str2的字符串长度。
|
||||
*/
|
||||
//let str2: &str = t.as_str();
|
||||
lstr = longest(str1, str2);
|
||||
}
|
||||
println!("longest str is {}", lstr);
|
||||
}
|
||||
{
|
||||
// 这里固定返回x,将生命周期的标注放在x和返回值上,
|
||||
// 这里必须标注生命周期,因为虽然我们知道返回值是x,但是编译器并不会分析代码的执行,
|
||||
// 所以这里必须显式的标注x和返回值的生命周期
|
||||
fn longest<'a>(x: &'a str, y: &str) -> &'a str {
|
||||
x
|
||||
}
|
||||
let str1 = "str1 ....";
|
||||
let lstr;
|
||||
{
|
||||
let t = String::from("str2");
|
||||
/* 因为longest的返回值的生命周期固定和x相同,
|
||||
那么这里即使传入的y是一个临时的字符串的引用也不会有问题。
|
||||
*/
|
||||
let str2: &str = t.as_str();
|
||||
lstr = longest(str1, str2);
|
||||
// 但是如果将str2传入x那么就会报错,因为str2的生命周期不足以在大括号外使用
|
||||
//lstr = longest(str2, str1);
|
||||
}
|
||||
println!("longest str is {}", lstr);
|
||||
}
|
||||
{
|
||||
#[derive(Debug)]
|
||||
struct test<'a, T> {
|
||||
str1: &'a T,
|
||||
}
|
||||
|
||||
let var;
|
||||
{
|
||||
let t = String::from("str1");
|
||||
var = test { str1: t.as_str() }; // 使用t的字符串引用
|
||||
println!("test: {:?}", var);
|
||||
}
|
||||
//println!("test: {:?}", var); // 在t的生命周期结束后在使用就导致报错
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user