For example, I want to declare a class but I want the client to not be able to use the copy constructor (or copy assignment operator)
Both of the following two does
Making a constructor private was basically a "hack" in the old C++, since it was the only way to prevent users from using them. The ability to delete
special member functions was only introduced in C++11, and it's the better and more idiomatic way to say that a class cannot be copied. since it is explicit about the intention.
Private constructors have other uses other than forbidding their use entirely (e.g. they may be called by static class member functions). So just making a constructor private doesn't communicate the intention very well, and the resulting error is not very clear, either.