At very first: Have a look at the rule of three, it is an absolute must go in given case. Consider, too, the rule of five, while not mandatory, you'll leave out a great optimisation opportunity...
The destructor would now delete[] the array (leaving this part to you...), a copy constructor would then do exactly that: (deep) copy the data:
A::A(A const& other)
   : a(other.a), b(new int[20]) // assuming you have a fixed size for those arrays;
                                // better: introduce a constant for to avoid magic
                                // numbers in code!
{
    // you created a new array, but yet need to fill it with the others value
    std::copy(other.b, other.b + 20, b);
}
OK, first step. Using the copy and swap idiom, the assignment operator gets pretty simple:
A& operator=(A other) // YES, no reference! This will invoke the copy (or move!)
                      // constructor of your class!
{
    swap(*this, other); // you'll need to implement it yet!
    return *this;
    // at this point, the destructor of other will clean up data that was potentially
    // contained in *this before...
}
Finally the move constructor:
A::A(A&& other)
   : a(0), b(nullptr)
{
    swap(*this, other);
    // again swapping??? well, sure, you want the data from other to be contained
    // in *this, and we want to leave other in some kind of valid state, which the
    // nullptr is fine for (it's fine to delete[] a null pointer, so you don't even
    // need to check in the destructor...) 
}
And now up to you: class B analogously...
Side note: you get away a bit cheaper by use of a smart pointer (std::unique_ptr), it will allow you to default destructor and move constructor + assignment operator, solely copy constructor and assignment operator need to be implemented explicitly (std::unique_ptr is not copiable...).