About pass arg as reference vs pass ownership

I get confused about argument sometimes, if I should be using reference or value in some function signature.

The mental model that I'm trying to follow is: If that function is the last step in the lifetime of some data (e.g. write it to a file), I pass the ownership of the data to the function. Otherwise, I pass it as a reference.

Is this a good way to think about lifecycles?

I think that is good way of thinking about it.

From my limited experience I think the pattern is that a function should do as little cloning/allocation as possible -- if it needs an ownership of the value (or even ownership of a transformed value via From/Into), pass the ownership of the value into the function. Let the caller create clones, they know better whether they even need to clone or just pass the ownership of an existing value.

2 Likes

For function arguments you'd almost always use references. Exceptions are:

  • Constructors like fn new(val) -> Self may prefer to take ownership of args they're keeping, so that they don't need to call to_owned()/clone() when the caller may already have an owned object. You can support both owned and borrowed args with impl Into<SomeOwnedType>.

  • When you want to enforce that an object can't be used after a method call, like connection.close(), make the method take ownership of self.

  • Small Copy values, like integers. They're more efficient to pass by value.

2 Likes