Software can be hard, so in order to make it more manageable, we’ve invented a lot of abstractions that let us reduce the number of moving parts via all sorts of constraints - we use types to restrict the set of possible values, permission modifiers to reduce their visibility scope, const modifier to prevent variables from being modified and other mechanisms to make invariant checks more tractable. In fact const modifier is so useful that some modern programming languages, e.g. Rust, assume it by default and instead require a modifier for mutable variables.
Over time I’ve developed a habit of using const as often as possible and expected that this should never hurt and possibly help compiler to apply additional optimizations. At some point I got puzzled about why struct fields in Rust are mutable but haven’t had time to research this and moved on.
Recently I was ramping up with new project and was doing a lot of source code reading. And while at it, why not follow the boy scout rule and leave it better then I found it. So, let’s get to work
The code above wastes an opportunity to reuse storage passed to consumer and ends up making an unnecessary copy
but, fortunately, modern C++ makes this easy to fix just by adding our favorite std::move
This simple change replaces usage of the expensive copy constructor with generously provided by the compiler move constructor
Nice. And just when I was about to move on, I’ve decided to add a const modifier to bytes field as it wasn’t modified after construction.
And that’s where my subconsciousness reminded me about mutable fields in Rust structs. So before sending changes for review, why don’t we take a look at the generated assembly to see if we’ve magically got some improvements?
Ouch! Looks like we’re back to square one with these pesky copies. But why? Well, the answer becomes fairly obvious when we think about what would default move constructor do - it would try to steal the guts of the “bytes” vector. But how can do this if it’s const? It can’t, so compiler has no choice but to resort to copying.
This is somewhat unfortunate that 2 C++ features I like have this tension but until it’s resolved we have to choose between move semantics and const fields.
Can you please explain the Rust part? I thought everything, including a struct fields are immutable by default. see here: https://stackoverflow.com/questions/47748091/how-can-i-make-only-certain-struct-fields-mutable