4 ms·
> string_view might be the only exception I can think of. What about std::span? std::optional? etc.
by dataflow 3y ago
> string_view might be the only exception I can think of.
What about std::span? std::optional? etc.
- nemetroid 3y agostd::span should apply, but std::optional is at least as large as the type it wraps.
- fyrn_ 3y agoAlmost always 8 + the size of the type. Since it's a one byte book followed by 7 padding bytes, followed by the type itself.
- vitus 3y agoView types like span, string_view, FunctionRef: absolutely pass by value. They're designed to be cheap to copy, and they provide type erasure which can make your API more flexible. You also usually want to pass smart pointers (unique_ptr, shared_ptr) by value to avoid breaking your ownership model, or pass by raw pointer or reference to the held data. The obvious case that comes to mind where you'd want to write const unique_ptr<T>& is when iterating over a vector<unique_ptr<T>>. Otherwise, pass ptr.get() for an optional param, or *ptr for a required param where you've already checked ptr != nullptr. Wrapper types like optional, variant, StatusOr? Usually pass by reference, unless the pointed-to type is small (<= 8 bytes). One common pattern where I see wide structs being passed by value is the use of option structs (https://abseil.io/tips/173 https://abseil.io/tips/173) that are usually constructed via designated initializers. There is some marginal benefit to being able to std::move() out individual fields but it's not really a big deal either way, as said computation is usually only done once on program initialization.