Итератор — это объект с семантикой указателя, который может указывать на N+1 точку в объекте.

Раз он с семантикой указателя, у него есть операции «унарная звезда» и −> (разыменование и разыменование+взятие поля). Также у итератора есть операция ++ (сдвинуться на следующую позицию). Если это т.н. «однонаправленный итератор» — всё, больше ничего.
Также бывают т.н. двунаправленные итераторы (есть операция −−), и итераторы произвольного доступа (их можно свободно складывать с числами — ну совсем как указатели). В частности, у std::list итераторы двунаправленные.
У итераторов неопределённое поведение…
• при попытке выйти за начало или конец;
• при попытке разыменовать, если он смотрит на последнюю позицию (отмеченную как «конец»).
Конкретно о задаче.
1. std::vector предпочтительнее std::list.
2. Не нужно возвращать string*, хватает какого-нибудь контейнера (std::vector<std::string> или std::list<std::string>).
3. Если функциональности и скорости istringstream хватает, флаг в руки! Я бы написал по хардкору, с нуля. Вот мой код, выдранный из моего проекта, наверно, будет несложно переделать его в учебный.
void parseCommaList(
        const char *aStart,   // указатель на начало
        const char *aEnd,    // указатель на символ за концом
        char aComma,        // символ-разделитель
        bool aSkipEmpty,   // true, если пустые подстроки пропускать
        ProcParseCommaList aCallback,   // функция-нагрузка
        void *aData)   // этот параметр нужен, чтобы передавать какие хочешь данные в функцию-нагрузку, удаляй его смело!
{
    str::trim(aStart, aEnd);    // моя функция; пододвигает aStart вперёд и aEnd назад, убирая пробелы.
                                // Если удаление пробелов не нужно — удаляй! Если нужно — пиши сам.
    if (aStart == aEnd) return;
    const char *sstart = aStart;
    for (const char *p = aStart; p != aEnd; ++p)
    {
        if (*p != aComma) continue;
        const char *send = p;
        str::trim(sstart, send);   // то же самое, можно убрать
        if (p != sstart || !aSkipEmpty)
            aCallback(sstart, send, aData);    // замени на боевую нагрузку
        sstart = p + 1;
    }
    str::trim(sstart, aEnd);   // то же самое, можно убрать
    if (sstart != aEnd || !aSkipEmpty)
        aCallback(sstart, aEnd, aData);    // замени на боевую нагрузку
}
И, соответственно, версия для std::string.
inline void parseCommaList(
        const std::string &aIn,
        char aComma,
        bool aSkipEmpty,
        ProcParseCommaList aCallback,
        void *aData)
{
    parseCommaList(aIn.data(), aIn.data() + aIn.length(), aComma, aSkipEmpty,
            aCallback, aData);
}