I am not very familiar with the C++ mutation interface so I will let Wouter answer those details.
The general performance advantage of flatbuffers is that memory can be read directly without allocating memory like you would when reading msgpack, json, protobuf etc.
As soon as you start to do any complex changes you essentially have to write a new buffer. Various experimental or less experimental api's may buffer changes before writing them out, which can be fast compared to alterternatives, or not, but it is not where you find the primary benefits of flatbuffers.
For very simple changes you can modify the memory of a flatbuffer in-place. For example and integer can change value from 42 to 27. A vector of integers can change each element in the same way, but it cannot change its length without either wasting space (truncation), or rewriting the entire buffers (extension). In C++ this can be very fast. In C it is not supported, in part because it is unsafe and is of limited use. For other languages I doubt this is supported, but I don't know.
Default values are not stored in the buffer, it is a value the generated code returns when a value is absent, so changing the value is not possible without rewriting the buffer.
Direct changes in flatbuffers is not safe if you do not 100% trust the flatbuffer - even if you verify the buffer it is not thorough enough to be safe when the buffer is modified, so I will not recommend it in most cases. The problem is that two different sub-structures of the buffer can be valid while placed on top if each other. Flatbuffer builders never do this, but it is possible. and a verifier will usually accept this. If you then start changing the buffer, this can trigger buffer overruns, for example if a vector length and a hit counter uses the same memory in the buffer and you change the hit counter.
Direct, or indirect changes of flatbuffers limits portability because the supported logic for doing so likely varies signficantly between languages, and even if supported, it might be relatively expensive to do in some languages while nearly instant in C++.
I believe there can be done much more in flatbuffer API world in different languages for buffering changes but the C++ API already does some work here - facebook did some work on their own that hasn't been released.
In conclusion, write flatbuffers, read flatbuffers, write new flatbuffers. If you are lucky, the API allows you to easily copy data from the old buffer into a new buffer, but this support varies by language and is most mature in C++ with help of reflection (which is not optimally fast because it does not use code generation for copying complex structures).
If you need extensive modificatins, a really fast json parser is an interesting alternative - it is slower because of memory allocations, but these allocations also make it simpler to mutate, and json can be read as flatbuffers if you use a compatible subset of json. In C flatbuffers based json parsers and printers are only 4 times slower than building a native flatbuffer. - but these do not support mutations.