Because of differences for zero initialization between compilers when using () {}
There is no difference. It is standardized and hasn't been changed significantly since C++03 in the case of () and since C++11 with the addition of {}. In particular both () and {} would have the same effect if your class didn't have a constructor and both would zero-initialize. If your class does have a user-declared/provided constructor, then the class isn't aggregate and so neither () nor {} will cause zero-initialization.
The memset on the other hand has implementation-defined behavior at best. In particular int(&b) is only allowed if int is large enough to hold a pointer value (i.e. it will fail on common 64bit systems). If it does work it has an implementation-defined value and everything you do with it is also implementation-defined.
Whether memset on a pointer to x instead of the A object is allowed at all, is another issue of concern.
If A wasn't trivially-copyable, then memset would have undefined behavior regardless.
The correct way to zero-initialize all members of a class explicitly with a non-aggregate class, i.e. one that has a user-declared/provided constructor, is to use the member initializer list to individually value-initialize the members, since C++03 like this:
A() : x(), y(), a(), b() { /* do constructor things */ }
(With C++11 or later {} default member initializers may be used instead as well.)
This initializes everything to zero, except padding. If you really need that for some reason and your class is trivially-copyable and *this isn't potentially overlapping (i.e. it isn't used as a base class subobject or a member subobject with [[no_unique_address]]), then a correct memset use would be:
memset(this, 0, sizeof(*this));
However, note that memseting all bytes to zero technically also doesn't imply that the members will be set to value zero. It is valid for an implementation to use a different bit pattern than all-zero to represent the zero or null pointer value of a scalar type.