[rust-dev] Newbie questions about memory management

Niko Matsakis niko at alum.mit.edu
Sun Dec 30 06:48:28 PST 2012


You have two options.

If you wish to use a borrowed pointer, you may write the function 
`new()` like so:

static fn new(value: &lifetime/str) -> StringReader/&lifetime {
StringReader { data: value, next: 0 }
}

The notation StringReader/&lifetime is (probably) not well-documented.  
What it means is: "a StringReader instance which contains borrowed 
pointers with the lifetime `lifetime`".  So basically it is specifying 
the lifetime of the `value` field, in this case.  Note that if the 
`StringReader` had multiple borrowed pointers contained within, they 
would all have to have the same lifetime.

Alternatively, you could have the StringReader own the data it is 
reading from, in which case you would want to use an `@str` or `~str`, 
just as you showed.  Ultimately, we would probably want both types in 
the standard library, since each can be useful in different circumstances.

Regarding your second question, the compiler makes some effort to 
construct data precisely into the location where it is needed.  So in 
the constructor function above, what happens is that a pointer into the 
caller's stack is passed as an implicit first parameter.  The struct is 
then written directly into the caller's stack.  This works so long as 
the return expression itself constructs the struct (more generally, so 
long as you return an rvalue).  It would not work if you stored the 
struct into a variable and returned that.

e.g., although there is no semantic difference, this program would *not* 
be optimized:

static fn new(value: &lifetime/str) -> StringReader/&lifetime {
   let r = StringReader { data: value, next: 0 };
   return r;
}

Here the compiler would produce a memcpy.


Niko



Colin Fleming wrote:
> Hi all,
>
> I'm playing around with Rust a little having been interested in it for 
> a while. I've read the language and borrowed pointers tutorials but 
> I'm still struggling with what seems like a fairly trivial example.
>
> I have a StringReader type:
>
> struct StringReader {
> data: &str,
> mut next: uint
> }
>
> and I'm trying to create a constructor for it:
>
> impl StringReader {
> static fn new(value: &str) -> StringReader {
> StringReader { data: value, next: 0 }
> }
> }
>
> I can't do this because the compiler "cannot infer an appropriate 
> lifetime", which I take to mean that it can't work out the lifetime of 
> 'value', probably because I shouldn't be using a borrowed pointer here.
>
> I tried a named lifetime, to indicate that the returned StringReader 
> pointer should be valid as long as the string is:
>
> static fn new(value: &lifetime/str) -> &lifetime/StringReader {
> &StringReader { data: value, next: 0 }
> }
>
> but that doesn't work either since the lifetime of the return value is 
> not the same as the lifetime of the param.
>
> I also tried by value:
>
> struct StringReader {
> data: str,
> mut next: uint
> }
>
> static fn new(value: str) -> StringReader {
> StringReader { data: value, next: 0 }
> }
>
> but to my amazement "bare `str` is not a type" - I'd expected this 
> just to create an inefficient copying version.
>
> The only thing I've managed to get to work is an owned string:
>
> struct StringReader {
> data: ~str,
> mut next: uint
> }
>
> static fn new(value: ~str) -> StringReader {
> StringReader { data: value, next: 0 }
> }
>
> Is this my best option here? What is the best practice for constructors?
>
> Another thing that I don't quite understand: according to the 
> tutorials, a struct constructed so:
>
> StringReader { data: value, next: 0 }
>
> is allocated on the stack. How does this work with the return value of 
> the constructor? Since the return value is only in scope in the 
> constructor body, I suppose this means that the return value of the 
> constructor is copied - isn't this inefficient for constructors?
>
> Thanks for any and all clarification,
> Colin
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20121230/7e3f8f1d/attachment.html>


More information about the Rust-dev mailing list