In your case (you want to avoid cluttering the build tree), a practically useful solution might be to have some convention about temporary executables.
For example, you could decide that every intermediate executable or file is named *.tmp or _* or *.tmpbin (for temporary binaries) and have some Makefile rules which removes them. Or you could use mktemp(1) in your Makefile to get a temporary file name. Don't forget to remove it later.
Also, most big projects have a compilation step and an installing step (often make install); and if you don't have that you probably should. You want your installing step to avoid installing the temporary binaries or files; with some naming convention this is quite simple: the first command for install phony target in your Makefile would remove these temporary binaries or files.
Also, you generally build in a file tree different of the final bin/ directory, so you could leave the temporary executables in the build tree.
As several people noticed, removing its own executable is easy on Linux (do a readlink(2) on "/proc/self/exe" (see proc(5) for details) then unlink(2) the result of readlink....) but difficult on Windows.
So practically your question is not a very important issue.... (if you use suitable build conventions). And GCC work on files (because it will run ld internally to build that executable file); however GCCJIT is hiding them. AFAIK, you won't even be able to use /dev/stdout as the executable output of gcc (but you can run gcc -x c /dev/stdin to compile C code from stdin). So GCC cannot avoid making an executable file (but you could have it temporary, or in a tmpfs file system or a FUSE one). So you need something external to your gcc command (perhaps simple an rm in some following line of your Makefile) to remove the produced executable.
You could also decide to have (dynamically loaded) plugins (e.g. use dlopen(3) on Linux). Your main program could load a plugin (with dlopen on Linux) - perhaps even after having generated dynamically its C++ code and having compiled that generated code into e.g. some shared object .so on Linux (or some DLL on Windows), as I do in MELT -, run functions in it obtained with dlsym, and unload the plugin (with dlclose on Linux) and finally remove it. You might use cross-platform frameworks like Qt or POCO to avoid dealing with OS specific plugin code.