>>does the C++ standard permits a C++ compiler/optimiser to use a sort of "copy on write" optimisation for the specific case I mentionned?
No. C++ implements value-semantics. This means that two different objects can never be two references to the same object. You can, of course, have two references or pointers to the same object, but that is entirely under your control, the compiler has little to do with that.
There are certain optimizations that the compilers are allowed to do when it comes to base versus derived class pointers. That is, if you hold a pointer to a base-class object, but the context makes it obvious to the compiler that the object is of a particular derived class, the compiler is allowed to by-pass the virtual function call and make an ordinary function call to the function it knows will be called anyways via the virtual dispatch mechanism. For example, a trivial case:
#include <iostream>
struct B {
virtual void print() const = 0;
};
struct D : B {
virtual void print() const { std::cout << "Hello World!" << std::endl; };
};
int main() {
D d1;
B* b1 = &d1;
b1->print(); //here, the compiler will most likely by-pass the virtual table look-up because it is clear from the context that b1 actually points to an object of class 'D', and so, it can call D::print() directly.
return 0;
};
You can try the above and output the assembly listing for it and you will see that the virtual table look-up (or virtual dispatch) is by-passed and optimized away. But note here, that the compiler is allowed to do this only when it is absolutely certain, from the local context, that there is no possible way that the base-class pointer could point to anything other than the derived class in question. In other words, the compiler is allowed to do this optimization only if it is guaranteed not to change the behaviour of the program. And this rule holds true for almost all optimization opportunities in C++ (with the notable exception of the "return-value-optimization", which is allowed to change behaviour by opimizing away some constructor/destructor calls).
EDIT: From your last post, clearly NO. To the compiler, you are creating two different objects, there is no way, absolutely no way, that the compiler would be allowed to "merge" the two objects, for any reason. I know that Java and C#, which implement reference-semantics (not value-semantics) can do certain crazy things of that nature (but I don't think it would do that particular example-case, because it makes no sense at all).
Even in this case:
struct B{
const int v=100;
virtual int get_derived_value()=0;
};
struct D1:B{
int v1;
int get_derived_value(){return v1;}
D1():v1(1000){}
};
void myfct(){
D1 d1;
D1 d2 = d1;
B* bp1=&d1;
B* bp2=&d2;
if (bp1==bp2){
//this code will NEVER execute, the compiler will not implement "copy-on-write" because C++ has value-semantics!
}
}
In the above case, as before, the compiler could by-pass the virtual dispatch, but the conditional will never evaluate to true. If you want copy-on-write mechanisms in C++, you have to implement them yourself, the compiler does not do that under any circumstance... C++ is not Java.