我正在编写以下测试代码。
fn test() {
let mut m = HashMap::new();
m.insert("aaa".to_string(), "bbb".to_string());
let a = m["aaa"]; // error [E0507] cannot move out of index of `HashMap<String, String>`
let a = m.index("aaa"); // ok, the type of a is &String. I think The compile will add & to m;
let a :&String = (&m).index("aaa"); // ok, the type of a is &String.
println!("{:?}", m["aaa"]); // ok
}
我不明白为什么m["aaa"]
的返回类型是String
,而不是&String
。因为索引(&self, key: &Q) ->特性Index
的V有一个&self
参数,我认为编译会给m添加一个&
, m["aaa"]的返回类型应该是&String,所以String "bbb"不会被移出m.
如果编译没有添加&对于m,它不会找到index()方法,错误应该像m cannot be indexed by "bbb"
;
From docs forIndex
:
container[index]
实际上是*container.index(index)
的语法糖
所以当你写m["aaa"]
时,编译器实际上是添加了一个*
来解引用Index::index
返回的值,而当你调用m.index ("aaa")
时,你直接得到&String
引用。
正如@user4815162342所指出的,程序员应该通过编写&m["aaa"]
或m["aaa"].clone()
来明确他们的意图。
此外,println!("{:?}", m["aaa"]);
可以工作,因为println!
宏确实为它访问的所有值添加了一个&
,以防止由于显示而导致的意外移动,这抵消了编译器添加的*
。
(1)这在format_args!
宏的文档中间接记录。