In C++, how is signed integer stored?
The C++ specification does not prescribe any particular storage representation for signed integers on the actual hardware level. An implementation is free to store signed integers however it wants.
C++ only prescribes the behavior of signed integers, not the representation. (That's not just true of signed integers, and not just true of C++. Almost every programming language does not specify particular representations, for any type.)
To be more precise: the ISO C++ specification describes the behavior of an ISO C++ Abstract Machine, but there is no requirement that the actual hardware must behave this way.
There's two's complement, one's complement, and sign/magnitude.
Until recently, C++ was very careful to define the behavior in such a way that all three of the above-mentioned representations (two's complement, one's complement, and sign/magnitude) can be used without incurring a performance penalty.
However, that has recently changed. ISO C++20 was the first version of C++ that removed support for one's complement and sign/magnitude. Note that this still does not mean that ISO C++20 requires signed integers to be stored in two's complement representation. It only means that conforming implementations must behave AS-IF signed integers were stored in two's complement representation.
Also, note that the C++ Committee explicitly chose to leave some behaviors as Undefined Behavior even though they could now theoretically be implementation-defined or even well-defined.
See also this Stack Overflow question: Ramifications of C++20 requiring two's complement
The ISO C working group has watched this with interest and is also considering removing support for anything other than two's complement representation from ISO C.
For Visual C++, which one is implemented?
Microsoft Visual C++ only supports (or at least supported at one point or another) a limited number of platforms (Windows NT, Windows CE, Windows, DOS, maybe some others I can't remember off the top of my head) and a limited number of architectures (AMD64, x86, ARM64, ARM, Alpha, MIPS, Sparc, PowerPC, PPC64, i860). For all possible combinations of those which are supported by Microsoft Visual C++, it uses two's complement representation, which is also the representation that is natively used by those architectures.
Even before ISO C++20, Microsoft Visual C++ has only ever supported two's complement representation.
Is this architecture dependent or maybe compiler dependent?
It is both. Although it is unlikely that a compiler would choose a different representation than the native representation of the architecture, that is entirely possible and allowed by the standard. It will just be somewhat slower because of all the conversions back and forth the compiler has to generate.
It looks like all the architectures which are supported by modern C++ compilers are two's complement, and none of the compilers for architectures which aren't two's complement support modern versions of C++. Therefore, there was no harm in removing support for anything except two's complement; current mainstream compilers didn't need to do anything, because they were already using two's complement.
The only known compiler which doesn't use two's complement is the Unisys Clearpath MCP C compiler, which uses sign/magnitude. However, that compiler only supports ISO C90 and has not been updated since 2017. So, if a future standard removes support for sign/magnitude, it is highly unlikely that Unisys will all of a sudden want to release a new version of their compiler which implements ISO C 2027 or whatever the next version will be.
Which means that the days of non two's complement representations are over in C++ and numbered in C.
But again, this only concerns the behavior, not the actual storage. As long as a program cannot actually notice that signed integers are not stored in two's complement representation, you can store them as pieces of cheese if you want.