What do you mean by wasteful? the enqueueFillBuffer functions are really self-documenting, they are meant to be used to fill buffers. Mapping and unmapping is another option, but the problem is that your memory usage spikes up if your buffer is large, unless you do it in small increments in which case you end up calling the API a lot which can also hurt (and isn't very elegant).
Of course, it's only available under OpenCL 1.2, so if that's the only 1.2 feature you're using it might make more sense to use a less modern approach and just implement the fill function yourself (it's actually not too hard, just enqueueWriteBuffer the given pattern over the entire buffer, just remember to use CL_FALSE for non-blocking writes, for the love of god).
Another option is to write a kernel designed to set buffers to zero, which might actually win out to every other approach bar zero-copy memory for large buffers on hardware devices (like GPU's) but this is very inelegant and tedious in terms of implementation. Though I'm not exactly sure how the enqueueFillBuffer is implemented, perhaps it uses that under the hood when appropriate.
Also, don't make the mistake I did. Don't foolishly memset an array of floats to zero. When I did that, it set them all to NaN in the OpenCL kernel for some reason