My understanding is that TBB finds out how many threads can comfortably run on a particular machine, i.e., without oversubscription, sets up the total number of threads to be that number by default, and lets the operating system figure out the rest. Also, unless I'm mistaken, it's not exactly the number of cores that matters, but the number of hardware threads, so, e.g.,one core and 2 hyperthreads would still give you two TBB threads.
TBB does not bind threads to cores. We believe this is the job of operating system to schedule threads in the best possible way, given current state of the system at whole. And we assume OS does its best to re-bind threads to the same cores where they run before, especially if the system is not oversubscribed. The affinity mechanism in TBB maps tasks to threads, in the above mentioned assumption. Meanwhile, in many cases TBB uses internal mechanisms (such as scheduler bypassing, stealing rules, etc) to ensure good cache locality.
As far as I know, no user-specifed binding (affinity masks and etc.) can guarantee thread will never migrate. OS still leaves itself some freedom of assigning a thread to a non-specified core, at least temporarily.
Binding provided by POSIX and Win32 API is STRICT, which means that on return from the function call target thread can not run on the non-specified processors. Though not sure what happens when processor goes down or when host OS changes number of VM processors...