The Args class was trying to maintain two parallel argument vectors. One that owned the memory and contained std::strings, and one that contained const char *'s that could be used similar to how argv is used.
But dealing with pointers to pointers is unsafe and should be avoided wherever possible. Furthermore, there doesn't seem to be much point in maintaining a second copy of the array, as it only serves to complicate the parsing logic since the two have to be kept in sync with each other, and really, the master copy has everything you need, including the null terminated strings.
So I removed m_argv entirely. The Args class will also no longer vend a const char**, and instead you can pass it a std::vector<const char*>& and it will fill it with null terminated argument strings. This can be used exactly like a const char** by writing &args[0], but now you have to explicitly opt into this, and by default you just get a nice safe container that can be used for example in ranged based fors. And the logic is simplified as well since the two arrays don't have to be kept in sync with each other.
All tests pass on Windows.
I think doxygen will complain about @return in a function returning void.
BTW, with the NRVO, move semantics and everything, is there any reason to keep using the return-through-reference-argument pattern? It would be a lot more natural if this indeed _was_ a return value.