As a C and C++ programmer I have used
It's actually much more complicated than you'd think. The OS thinks of everything in "pages", it splits the RAM into pages, and the hard drive into pages. When your program starts, it checks how much memory your executable takes, chooses some RAM pages for it, and assigns those pages to your program. If there's no "usable" pages in RAM, it takes older some pages in RAM, and saves them to the hard drive somewhere tucked away, and then gives those pages to you.
When you allocate memory in your program, the memory manager of your program will try to find a free spot in the pages the operating system has assigned to it. If there's not enough, it asks the operating system for more pages, and the operating system makes more room and gives your application more pages.
If your program has a page that it hasn't used in a while, (even code sometimes), the operating system may save that page to the hard drive, and when your program tries to use that page again, the operating system pauses your program, reloads the page into RAM, and then resumes your program.
Here's a diagram that makes no sense
C++ addresses RAM hard drive +------------+ +------------+ +------------+ | 0x00010000 |\ ->| 0x00010000 | | 0x00010000 | +------------+ X +------------+ +------------+ | 0x00020000 |/ ->| 0x00020000 | | 0x00020000 | +------------+ +------------+ +------------+ | 0x00030000 |-->? /----->| 0x00030000 | +------------+ / +------------+ | 0x00040000 |-----------/ | 0x00040000 | +------------+ | etc |
So in this code, your code has stack memory of 0x00010000-0x0002FFFF, and you've allocated some dynamic memory, and that's in 0x0004000. AS FAR AS YOU KNOW! In reality, when you access 0x0002000, the operating system says "oh, I've stored that page of yours in the RAM address 0x00010000" and reads those values for you. You haven't touched the page of 0x00040000 in a while, so the operating system saved it to the harddrive at harddrive location 0x00030000, but will bring it into RAM if you try to use it. The operating system hasn't given you the address 0x00030000 yet, so if you try to use it, the operating system will tell you that address doesn't have any actual pages, and you get a segmentation fault (segfault). What makes this interesting is when you ask for a large contiguous chunk like a vector, the operating system can give you any old pages it finds laying around, it doesn't have to worry if they're contiguous or not. They look contiguous to your program, which is all that matters.
This also allows the operating system to hide memory of one program from another, which keeps them from being able to read or modify other program's memory space. They're safe! Except... there are ways to tell the operating system to share a page between two programs (though they may have different addresses in each program), allowing them to share pages. DLLs do this.
In reality, it's far more complicated than this.