For loop has no direct relation to containers, it just allows you to do some block of code several times while condition is met.
Common application for For loop is to adjust some number sequentially and use it to access some element in contiguous array by that number as index (offsetting from the beginning).
As you've mentioned it does not work with data not aligned contiguously, but "For" loop is not limited to just updating indices. Iterator is a pattern of object that encapsulates logic of container traversal. Container provides methods for iterator obtaining and then iterator provides methods to move through container content in some direction.
With that you can use "for" loop (which is not bound to just updating indices!) with iterators to iterate through set elements
for (auto iterator = my_set.begin(); iterator != my_set.end(); iterator++)
// do something with element through iterator
C++11 "range-based for" feature just allows you to have a compact form for the same logic:
for (auto iterator : my_set)
// do something with element through iterator
Internally set forward iterator just moves through tree nodes in specific order, handling all the logic of next node selection, moving from left to right in binary search tree.
You can imagine that set::begin() returns an iterator that internally stores an address of the first node in set (leftmost leaf for forward iterator). Iterator::operator++ is implemented in a way to update iterator to reference next node in sorted order.
Informal logic of next item selection from iterator point of view:
If my node has left child - it is less than my element so I do not need to visit it. Right node is bigger than my element so it is the next element.
If my node has no right child - i need to move up to find next element. I need to know whether I go up from left direction or right. If I am moving up from the left subtree - then value of parent node is next ordered value. If I am moving from the right subtree - I visited this node already and I need to recursively continue my ascension while I will find that I approached node from left subtree. If no such node found - that means that I've just pointed to last element so now I should invalidate internal reference to highlight that iterator reached the end of container.