In statement sample d= ++s; copy constructor is called. When you did not define your copy constructor sample(sample &s); ( when it was commented) the compiler created implicitly the following copy constructor sample( const sample &s);. The implicit copy constructor copies all members of one object of a class to another object. As in your example at first the pre-increment operator is called and after it the copy constructor is called then d.i is equal to 1.
When you uncomment your copy constructor it is used instead of the implicit copy constructor. Your copy constructor sets i equal to 0. So you get that d.i is equal to 0.
Also you can get in the second case that d.i will be equal to 1 due to allowed by the Standard optimization. That is the compiler is allowed do not use copy constructor to copy innamed temporary objact and to build it directly in object d.