today's rust mystery section 4.9 of rust programming language, first edition. example of references , borrowing has example:
fn main() { fn sum_vec(v: &vec<i32>) -> i32 { return v.iter().fold(0, |a, &b| + b); } fn foo(v1: &vec<i32>) -> i32 { sum_vec(v1); } let v1 = vec![1, 2, 3]; let answer = foo(&v1); println!("{}", answer); }
that seems reasonable. prints "6", you'd expect if v
of sum_vec
c++ reference; it's name memory location, vector v1
defined in main()
.
then replaced body of sum_vec
this:
fn sum_vec(v: &vec<i32>) -> i32 { return (*v).iter().fold(0, |a, &b| + b); }
it compiled , worked expected. okay, that's not… entirely crazy. compiler trying make life easier, that. confusing, have memorize specific tic of language, not entirely crazy. tried:
fn sum_vec(v: &vec<i32>) -> i32 { return (**v).iter().fold(0, |a, &b| + b); }
it still worked! hell?
fn sum_vec(v: &vec<i32>) -> i32 { return (***v).iter().fold(0, |a, &b| + b); }
type [i32] cannot dereferenced
. oh, thank god, makes sense. have expected 2 iterations earlier!
references in rust aren't c++ "names place in memory," are they? they're not pointers either, , rules them seem either esoteric or highly ad-hoc. happening such reference, pointer, , pointer-to-a-pointer work equally here?
the rules not ad-hoc nor esoteric. inspect type of v
, it's various dereferences:
fn sum_vec(v: &vec<i32>) { let () = v; }
you'll get:
v
->&std::vec::vec<i32>
*v
->std::vec::vec<i32>
**v
->[i32]
the first dereference understand. second dereference deref
trait. vec<t>
dereferences [t]
.
when performing method lookup, there's straight-forward set of rules:
- if type has method, use , exit lookup.
- if reference type has method, use , exit lookup.
- if type can dereferenced, so, return step 1.
- else lookup fails.
references in rust aren't c++ "names place in memory,"
they absolutely names place in memory. in fact, compile down same c / c++ pointer know.
Comments
Post a Comment