We regularly recommend customers use Boost if you need an API compatible version, or something like RE2 if you just need a fast regex engine.
The handling of repetition is more revealing, it doesn't appear to have "states" at all but rather is just the usual backtracking: https://github.com/microsoft/STL/blob/master/stl/inc/regex#L...
So the "NFA" is really an AST for the regex rather than an automaton based on Thompson's algorithm or similar.
PCRE's docs continue this confusion. For example, they expose a DFA API... But it's not actually a DFA!
One might say this is similar to how "regex" doesn't necessarily imply "regular," which is true. That's definitely a battle that has been lost long ago. But NFA and DFA are even more specific jargon terms, and the way in which they have been redefined by the Friedls of the world has led to exactly your confusion over and over again.
To be fair, the same thing happens with the Thompson NFA simulation. It's not too hard to add a little extra power to it in the form of memory in order to track capturing group locations. It becomes more powerful than an NFA with this addition, but retains its linear time bound. This is why I've normally seen this addition called the Pike VM. (At least, Russ Cox and I both use than name.)
For completeness, you can also use bounded backtracking to simulate an NFA. It keeps track of all states visited per input byte, so it uses a lot of extra memory, but maintains a linear time bound.
Also, backreferences stand a chance of turning an NFA into NIA. Turns out it's not possible to programmatically determine which backreference-containing regexes will halt or not.
How are backreferences implemented here?
1: https://github.com/microsoft/STL/blob/master/stl/inc/regex