-3

ENV: windows 7 x64, Visual Studio Community 2015

I am a newbie of cplusplus and stl. I am trying to find what a list iterator exactly is. I write two piece of codes, and iterator in both of them seems have a different value with the address of the list element. It looks wired that it still can get the value of element using operator *. Any references, ideas about this? Thanks for your time.

Codes with struct list:

#include <iostream>
#include <list>
#include <cstdio>

typedef struct st
{
    int m;
    int n;
}st_t;

int main (int argc, char *argv[])
{
    int *_i1, *_i2;
    st_t *pST;
    std::list<st_t> stList;
    std::list<st_t>::iterator iterSTList;
    st_t varST;
    varST.m = 1;
    varST.n = 10;
    stList.push_back(varST);
    varST.m = 2;
    varST.n = 20;
    stList.push_back(varST);

    for (iterSTList=stList.begin(); iterSTList!=stList.end(); iterSTList++)
    {
        pST = &(*iterSTList);
        std::cout << " pST->m " << pST->m << std::endl
                  << " pST->n " << pST->n << std::endl
                  << " (*pST).m " << (*pST).m << std::endl
                  << " (*pST).n " << (*pST).n << std::endl
                  << " pST " << pST << std::endl
                  << " &(*iterSTList) " << &(*iterSTList) << std::endl;

        std::printf("iterSTList %X \n", iterSTList);

        _i1 = &(iterSTList->m);
        _i2 = &(iterSTList->n);     
        std::cout << " _i1 " << _i1  << " iterSTList->m " << iterSTList->m << std::endl
                  << " *_i1 " << *_i1  << " (*iterSTList).m " << (*iterSTList).m << std::endl
                  << " _i2 " << _i2  << " iterSTList->n " << iterSTList->n << std::endl
                  << " *_i2 " << *_i2  << " (*iterSTList).n " << (*iterSTList).n << std::endl;

    }

    return 0;
}

result

pST->m 1
pST->n 10
(*pST).m 1
(*pST).n 10
pST 00323F90
&(*iterSTList) 00323F90
iterSTList 323960
_i1 00323F90 iterSTList->m 1
*_i1 1 (*iterSTList).m 1
_i2 00323F94 iterSTList->n 10
*_i2 10 (*iterSTList).n 10
pST->m 2
pST->n 20
(*pST).m 2
(*pST).n 20
pST 00323FD0
&(*iterSTList) 00323FD0
iterSTList 323960
_i1 00323FD0 iterSTList->m 2
*_i1 2 (*iterSTList).m 2
_i2 00323FD4 iterSTList->n 20
*_i2 20 (*iterSTList).n 20

See. the value of iterSTList is different with &(*iterSTList), but iterSTList can get the element value like a pointer

Codes without struct:

#include <iostream>
#include <list>
#include <cstdio>

int main (int argc, char *argv[])
{
    int *p;
    std::list<int> iList;
    std::list<int>::iterator iter;
    int m;
    m = 1;
    iList.push_back(m);
    m = 2;
    iList.push_back(m);

    for (iter=iList.begin(); iter!=iList.end(); iter++)
    {
        p = &(*iter);
        std::cout << " p " << p << " *p " << *p << std::endl
                  << " &(*iter) " << &(*iter) << " *iter " << *iter << std::endl;

        std::printf("iter %X \n", iter);

    }

    return 0;
}

result

p 007039D8 *p 1
&(*iter) 007039D8 *iter 1
iter 703998
p 00703A10 *p 2
&(*iter) 00703A10 *iter 2
iter 703998

same thing. the value of iter is different with &(*iter) and p. But *iter and *p get the same value.

Any thing wrong with my code? iter is an iterator, of course. Does it can be treated as a pointer sometimes? when? Thanks.

After compiling on VS 2015:

Severity    Code    Description Project File    Line    Suppression State
Warning C4477   'printf' : format string '%X' requires an argument of type 'unsigned int', but variadic argument 1 has type 'std::_List_iterator<std::_List_val<std::_List_simple_types<st>>>'  tlist2  c:\users\cnpc\documents\visual studio 2015\projects\tlist2\tlist2\source.cpp    35  
Nick Dong
  • 3,638
  • 8
  • 47
  • 84
  • 4
    The `*` operator is overloaded for iterators. I recommend a [good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – molbdnilo Feb 19 '16 at 07:30
  • 2
    And I recommend getting rid of VC6. – deviantfan Feb 19 '16 at 07:34
  • 2
    And a decent compiler! VC 6.0 is 18 years old. The [Visual Studio Community Edition](https://www.microsoft.com/en-us/download/details.aspx?id=48146) should be a good alternative. – smkanadl Feb 19 '16 at 07:35
  • Yes, I know. I have vs 2015 either. But I run those code piece with VC 6.0. Is there something wrong to use vc 6.0 to talk about iterator? – Nick Dong Feb 19 '16 at 07:42
  • 1
    @NickDong To start with, it's probably missing some members and/or guarantees. Because VS6 is way too old and has a reputation for not caring for standards anyway. – deviantfan Feb 19 '16 at 07:46
  • Thanks, @deviantfan I have re-build the code using vs community 2015. And I already change the result. And the result is different either. The value of iteraSTList is not change compiling by vs community 2015, while it is changed is vc 6.0. – Nick Dong Feb 19 '16 at 08:10

1 Answers1

1

what list iterator exactly is

It is an implementation defined type. It is in the category of BidirectionalIterators. std::list<T>::iterator is an alias of the type. That is all you need to know. Relying on any other knowledge about the type would be bad for the portability of your program. You should never rely on implementation defined details and it's sometimes better to not even know them.

iterator in both of them seems have a different value with the address of the list element.

I wouldn't have expected that the value would be equal to the address of the element. After all, the iterator is not a pointer. It should be apparent that it can not be a pointer if you consider what ++p does with a pointer and how linked lists work.

Any thing wrong with my code?

Yes. You're passing an iterator to printf which expects an unsigned int because of the %X specifier. By passing an object of wrong type, you have formally undefined behaviour.

Does it can be treated as a pointer sometimes?

Never.

As a side note: A pointer can be treated as an iterator to an array. That relation only applies to only contiguous data structures (i.e. arrays) and the relation is unidirectional. An iterator can not be treated as a pointer.

Any references

If the header file <list> is human readable, then you can open it and find out the name of the type which std::list<T>::iterator is an alias to. Then you should also find the definition of that type. The definition might be in a separate header file. It's highly unlikely that there would be any use for the knowledge.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • As @molbdnilo said that the * operator is overloaded for iterators. Although iterator is not a pointer, I still can use * and -> to fetch element in list. Right? – Nick Dong Feb 19 '16 at 08:20
  • @NickDong Correct. To meet the requirements of an InputIterator, it must implement `operator*` and `operator->` You can refer to this [wiki page](http://en.cppreference.com/w/cpp/iterator) for things that you can do with iterators. – eerorika Feb 19 '16 at 08:23