|
|
|
@ -45,7 +45,7 @@ let s = "initial contents".to_string();
|
|
|
|
|
let s = String::from("initial contents");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
因为字符串使用广泛,这里有很多不同的用于字符串的通用 API 可供选择。他们有些可能显得有些多于,不过都有其用武之地!在这个例子中,`String::from`和`.to_string`最终做了完全相同的工作,所以如何选择就是风格问题了。
|
|
|
|
|
因为字符串使用广泛,这里有很多不同的用于字符串的通用 API 可供选择。他们有些可能显得有些多余,不过都有其用武之地!在这个例子中,`String::from`和`.to_string`最终做了完全相同的工作,所以如何选择就是风格问题了。
|
|
|
|
|
|
|
|
|
|
记住字符串是 UTF-8 编码的,所以可以包含任何可以正确编码的数据:
|
|
|
|
|
|
|
|
|
@ -111,7 +111,7 @@ fn add(self, s: &str) -> String {
|
|
|
|
|
|
|
|
|
|
这并不是标准库中实际的签名;那个`add`使用泛型定义。这里的签名使用具体类型代替了泛型,这也正是当使用`String`值调用这个方法会发生的。第十章会讨论泛型。这个签名提供了理解`+`运算那奇怪的部分的线索。
|
|
|
|
|
|
|
|
|
|
首先,`s2`使用了`&`,意味着我们使用第二个字符串的**引用**与第一个字符串相加。这是因为`add`函数的`s`参数:只能将`&str`和`String`相加,不能将两个`String`值相加。不过等一下——正如`add`的第二个参数所指定的,`&s2`的类型是`&String`而不是`&str`。那么为什么代码还能编译呢?之所以能够在`add`调用中使用`&s2`是因为`&String`可以被**强转**(*coerced*)成 `&str`——当`add`函数被调用时,Rust 使用了一个被成为**解引用强制多态**(*deref coercion*)的技术,你可以将其理解为它把`&s2`变成了`&s2[..]`以供`add`函数使用。第十五章会更深入的讨论解引用强制多态。因为`add`没有获取参数的所有权,所以`s2`在这个操作后仍然是有效的`String`。
|
|
|
|
|
首先,`s2`使用了`&`,意味着我们使用第二个字符串的**引用**与第一个字符串相加。这是因为`add`函数的`s`参数:只能将`&str`和`String`相加,不能将两个`String`值相加。不过等一下——正如`add`的第二个参数所指定的,`&s2`的类型是`&String`而不是`&str`。那么为什么代码还能编译呢?之所以能够在`add`调用中使用`&s2`是因为`&String`可以被**强转**(*coerced*)成 `&str`——当`add`函数被调用时,Rust 使用了一个被称为**解引用强制多态**(*deref coercion*)的技术,你可以将其理解为它把`&s2`变成了`&s2[..]`以供`add`函数使用。第十五章会更深入的讨论解引用强制多态。因为`add`没有获取参数的所有权,所以`s2`在这个操作后仍然是有效的`String`。
|
|
|
|
|
|
|
|
|
|
其次,可以发现签名中`add`获取了`self`的所有权,因为`self`**没有**使用`&`。这意味着上面例子中的`s1`的所有权将被移动到`add`调用中,之后就不再有效。所以虽然`let s3 = s1 + &s2;`看起来就像它会复制两个字符串并创建一个新的字符串,而实际上这个语句会获取`s1`的所有权,附加上从`s2`中拷贝的内容,并返回结果的所有权。换句话说,它看起来好像生成了很多拷贝不过实际上并没有:这个实现比拷贝要更高效。
|
|
|
|
|
|
|
|
|
|