How to access an item within a list?

2

I am learning to use C ++ templates of stl and this library contains a class list<T> , I understand that it has functions similar to those of vector<T> (If not, please illustrate me) .

My question is, how can I access an element within an object of type list<T> in a certain index?

So far I have tried this:

std::list<int> Numeros = /* Mi asignación aquí */;
int n = Numeros[0]; // Error.

However, using std::vector<T> works perfectly:

std::vector<T> Numeros = /* Alguna asignación */;
int n = Numeros[0]; // Asumiendo que tenemos un elemento aquí, me devuelve el valor.

Is it possible to access the values contained within a list<T> using an index?

    
asked by NaCl 25.05.2016 в 19:33
source

3 answers

4

Although all the containers of the stl keep certain similarities regarding the use the certain thing is that each one internally works of different form, soon all the methods are not going to be available in all the containers.

  • std::vector represents an unordered list of elements. Its main characteristic is that all the elements are contiguous in memory, which allows random access. It is the default container for most situations.

  • std::list represents a linked list. Being a linked list Your items do not have to be contiguous in memory but to access the second item before you have to access the first. It is for this last reason why it does not admit random access although it does admit the sequential one.

Traditionally STL containers can be traversed universally using iterators:

for( auto it = contenedor.begin(); it != contenedor.end(); ++it )
{
  // ...
}

There are also functions within the STL that try to encapsulate this mechanics a bit:

  • std::foreach : Walk through a container and, for each element, execute a function passed by parameter
  • std::transform : It traverses a container and, for each element, executes an operation passed by parameter. The result of this operation is stored in a new container
  • std::find : It traverses a container looking for an element passed by parameter. Returns an iterator to the element or, if it is not found, the iterator given by contenedor.end()
  • std::find_if : Similar to the previous one but it supports a pointer to a function that implements the search criteria
  • std::reverse : Inverts the values that are between the iterators passed as a parameter (eye, in ordered containers, as set will not work)
  • ...

A new type of loop is also available from C ++ 11 that allows easy iteration over containers avoiding the use of iterators:

std::vector<int> lista(10);
std::iota(lista.begin(), lista.end(), 1);

for( auto item : lista )
  std::cout << item << std::endl;

Also, from C ++ 11, std::begin and std::end are available. These two functions allow you to obtain the corresponding iterators both in STL containers and in fixed size arrays (you can calculate their size at compile time):

std::vector<int> v = {1,2,3,4,5};
int arreglo[] = {6,7,8,9,10};

for( auto it = std::begin(v); it != std::end(v); ++it )
  std::cout << *it;
for( auto it = std::begin(arreglo); it != std::end(arreglo); ++it )
  std::cout << *it;

Other mechanisms to work with iterators are:

  • std::distance : Calculate the number of elements between two iterators
  • std::next : It allows advancing an iterator n positions
  • std::advance : Similar to the previous one, modify the last iterator as parameter

Well, all of the above was a bit of theory about the contenders and their possibilities. Answering your question now, yes, it is possible to access a specific position of both a std::list and any other container using iterators and std::next or std::advance .

In the specific case of std::list , it is not possible to access a specific element using the index operator [] because its elements are not in consecutive memory positions. Accessing a random element involves traversing a part of the nodes in the list and that task is performed by iterators and must be carried out explicitly.

Greetings.

    
answered by 26.05.2016 / 09:43
source
2

I have wandered through the documentation of stl and some questions of OS, I have encountered std::advance() and std::next() :

  • std::next(Vector, Numero) : Returns a pointer within the index (Parameter) Numero assignable, returns an element of the same type of vector. Documentation , it should be mentioned that without the parameter Numero this function advances to the next element of the Vector, so that this parameter is optional.

  • std::advance(Vector, Cantidad) : It works practically the same as std::next() unless it directly modifies the parameter Vector by the element located in position Cantidad and does not return any value. Documentation

Example with std::next(V,N) :

int main() 
{
    std::list<int> v{ 2, 8, 5, 6 };

    auto Iterator = v.begin(); // El valor inicial (begin) es: 2
    auto Siguiente = std::next(Iterator); // El valor de Siguiente es: 8
    auto SaltaTres = std::next(Iterator, 3); // El valor es: 6

    std::cout << *Iterator << ' ' << *Siguiente << ' ' << *SaltaTres;
    return 0;
}

Example with std::advance(V,N) :

int main() 
{
    std::list<int> v{ 2, 8, 5, 6 };
    auto Param = v.begin();

    std::advance(Param, 2); 
    // El valor de Param fué alterado por el nuevo valor que le asignó advance(); 
    // Por lo que ahora Param tiene el valor de: 5

    std::advance(Param);  // Error.
    std::cout << *Param;
    return 0;
}

It is worth mentioning that the parameter Cantidad that I have named in std::advance() is mandatory.

    
answered by 25.05.2016 в 20:59
1
 for(std::list<int>::iterator list_iter = int_list.begin(); 
        list_iter != int_list.end(); list_iter++){

        std::cout<<*list_iter<<endl;

}

int_list.begin() places a pointer at the beginning of the list

int_list.end() is a pointer at the end of the list

The pointer to the beginning of the list moves to the next element with pointer arithmetic: list_iter++

    
answered by 25.05.2016 в 19:46