In some cases you will find that the way your objects should be copied is not trivial.
If you consider the class :
class Car {
string BrandName;
int NumberOfPassenger;
}
Then it is clear that when you'll be copying two objects, you'll simply want to copy them member by member. There's nothing special to do here so the defaut copy constructor will work just fine.
But imagine that the class is instead :
class Car {
string BrandName;
int NumberOfPassenger;
Mechanics EngineeringStuff;
}
Here Mechanics is a reference type. What the copy constructor will do is simply copying the reference to the new object, so both cars - car1 and car2 - will share the same EngineeringStuff. But a more natural behaviour would be to allocate manually a new Mechanics object when performing the copy, so the cars don't share the same wheels, motors etc...
More generally, it's usually when you have to deal with reference types or certain kind of business logic that you will need to explicitly write your copy constructor.