The number of unused cells is infinite (or size of int^3) minus used cells... ^_^;
No, I don't think there's a way to know that (in general, 3D is weird when talking about size of things).
So your solution may be the best/quick/cheap way.
Every time you add a cell, max and min check x,y,z adding it to a pair of Vector3 or individual variables.
With that "extent" you keep, you can iterate over all the cells and get the internal ones that are unused (-1) with get_cell_item
.
One day, GridMap may get more features like TileMap, something like get_used_cells
could be handy (you are free to make a request on GH).