They are closely related. When you write one, you should write the other.
The other answerers are correct. The copy constructor is used when you write code like the following:
MyClass X = Y; //invokes copy constructor
MyClass X(Y); //also invokes copy constructor
whereas the operator = is called when you write code like the following:
MyClass X: //invokes default constructor
X = Y; //invokes operator =
Since you rarely see code like "MyClass X = Y", you might be tempted to skimp on the copy constructor. Don't. There's another sneaky place you often find copy constructors: passing variables by value. The standard template library does this ALL THE TIME, so if you have vectors or lists in your code, be aware of this.
MyClass Y; //invokes default constructor
DoSomething(Y); //calls copy constructor
std::vector
myVector;
// (pretend we added a bunch of items to vector here)
myVector.push_back(Y); //invokes copy constructor. May also invoke copy constructor on other items already added if vector resizes.
std::sort(myVector); //invokes operator= on any items that move
From the programmer's standpoint, one key thing to remember is that when you write the operator =, you MUST clean up anything you're pointing at already. For example, if you have a pointer in your class, you should free that pointer before copying the value from the right-hand side. Copy constructors tend to be faster than operator= for this reason.
Hope this helps.