as @Nawaz already noted:
When you have unstable objects, you need a flying copy-ctor. Therefore, the question boils down to the following: when do you need unstable objects?
The main reason for using the volatile keyword is usually to disable optimization. That is, if you have something like this:
bool flag = false; if(!flag) {}
The compiler will see that this flag cannot be changed, so there is no need to check the flag every time, so it will not. But if you make the flag volatile, it will be.
Here is an opinion on using volatile keyword: link
In short, it was originally used to access equipment through MMIO, which may be somewhat unusual:
unsigned char* pControl = 0xff24 ; *pControl = 0 ; *pControl = 0 ; *pControl = 0 ;
And you do not want these 3 appointments to become one of them thanks to optimization.
And here is an article by Andrei Alexandrescu about unsustainable multithreaded software: link
There were papers criticizing the newspaper Alexandrescu, but I could not find it. The fact is that he discarded volatile property, etc.
Remember the very important thing with multithreading that @JanHudec pointed out:
volatile absolutely useless for a multi-threaded context, because although it prevents optimization, it does not create obvious barriers. And without the fact that a recording made on one CPU may not become visible to another CPU (it depends on the architecture; x86 has consecutive caches, so the records are always visible there).
Also volatile does not force the operation to be atomic. When assigned, x86 is always atomic, but this does not apply to all CPU architectures. And more complex operations, such as incrementation, can only be done by atoms using std::atomic .