iteratores de flujo....inicializacion de vector, etc.

Iniciado por digimikeh, 28 Julio 2019, 23:57 PM

0 Miembros y 1 Visitante están viendo este tema.

digimikeh

Hola amigos.. que tal.

Tengo una gran duda, la verdad me confunde un poco el hecho de que se pueda inicializar una variable de 3 formas:

Código (cpp) [Seleccionar]

int x = 3;
int y {4};
int z(5);


Las 3 son válidas, bueno, así como se ve, no está complejo realmente, el problema es cuando usas elementos como un contenedor.. ya que los contenedores aceptan una lista de argumentos encerradas en llave, sin embargo esto me confunde un poco, porque no se cuando está inicializando o cuando está pasando por argumento a un constructor.. o cuando está usando un constructor de conversión.. etc..


Ejemplo:
Código (cpp) [Seleccionar]


vector<string> vs { "Hola", " Que tal"};     //No hay problema..
vector<string> vs2 { 5, 1 };                     //Houston

istream_iterator<string> is;
istream_iterator<string> is2;

vector<string> vs3{is, is2};                     //No hay problema.. por que?




Sospecho que en vs3 no estoy inicializando ... pensé que las llaves eran para eso... que esta pasando en esta línea?..


Saludos y gracias.


--------------------------------

Edito:

Estuve viendo los constructores que tiene std::vector y encontre uno que acepta un iterator de inicio y otro de fin... entonces eso es lo que debe estar aceptando, es decir,  vs3 no esta inicializando, solo le estoy pasando los iteradores que están conectados al flujo de entrada ifstream....  En el fondo lo que me habia confundido es el uso de las llaves, tenia entendido que las llaves servian para inicializar en los contenedores, pero ya vi que hace lo mismo que los parentesis, a menos que este poblando al contenedor, ahi seria una inicialización...

Saludos.
Dungeons & dragons;
dragons.Attack();

Loretz


int x = 3;
int y {4};
int z(5);

Y podrías incluir también a la cuarta:
int t = {6}; // copy initialization

Citar... el problema es cuando usas elementos como un contenedor.. ya que los contenedores aceptan una lista de argumentos encerradas en llave, sin embargo esto me confunde un poco, porque no se cuando está inicializando o cuando está pasando por argumento a un constructor.. o cuando está usando un constructor de conversión.. etc..

Hablando de objetos, "construir" implica "inicializar"; cuando se construye un objeto se lo está inicializando de alguna manera:

  • zero initialization
  • default initialization
  • direct initialization
  • value initialization
  • copy initialization
  • list initialization
Pudes empezar por https://en.cppreference.com/w/cpp/language/copy_initialization

Y con respecto a forma de construir un std::vector o cualquier contenedor de la biblioteca estándar, creo que lo mejor es tener siempre a mano su documentación, porque algunas veces lo que parece intuitivo no lo es tanto; y en particular, los constructores a partir de una std::initializer_list han tenido algunos cambios en C++17.

Citarvector<string> vs { "Hola", " Que tal"};     //No hay problema..  (1)
vector<string> vs2 { 5, 1 };                     //Houston (2)

istream_iterator<string> is;
istream_iterator<string> is2;

vector<string> vs3{is, is2};                     //No hay problema.. por que? (3)

Puedes ver los constructores de vector en https://en.cppreference.com/w/cpp/container/vector/vector
Por ejemplo, para
1) Construye (inicializando) vs con una "initializer list" de dos strings
2) Error: no hay un constructor para vector<string> que tome una initializer list de ints.
3) Invoca el constructor:
template< class InputIt >
vector( InputIt first, InputIt last,
        const Allocator& alloc = Allocator() );

aunque cuidado, en este caso estás usando un rango de dos iteradores nulos ("end of stram iterators") [https://en.cppreference.com/w/cpp/iterator/istream_iterator/istream_iterator]

Yo me quedaría con la idea de que cuando se va a utilizar alguna función miembro de una clase (constructor o lo que sea), siempre conviene tener la documentación a mano.






digimikeh

Entiendo, estará bueno siempre revisar la documentación...

Que vendría siendo ifstream ?.. un canal que conecta a un archivo, o el archivo mismo?
y que vendría siendo el istream_iterator ? un puntero que apunta al contenido del archivo o apunta al contenido del flujo?...

Trato de materializar estos objetos, como podrian ser representados concretamente?

Saludos y gracias.
Dungeons & dragons;
dragons.Attack();

Loretz

Como siempre, una simple pregunta puede tener una respuesta simple, o no.

Como regla de estilo general, las clases de la biblioteca estándar C++ (como casi cualquier otra cosa en el mundo) pueden usarse y/o entenderse; con una fuerte inclinación a "usarse" y como caso excepcional la parte de "entenderse". Es la forma que se adoptó para todo lo que llamamos conocimiento; no sé cuándo sucedió, pero cuando yo llegué ya estaba así.

Y en particular, hablando de
CitarQue vendría siendo ifstream ?.. un canal que conecta a un archivo, o el archivo mismo?
o de
Citary que vendría siendo el istream_iterator ?
tienes también las mismas opciones: un par de respuestas dogmáticas, del tipo "es así y deja de joder", o meterte en entender de qué se trata (que supongo que es un poco menos deshumanizante, aunque tampoco demasiado acojonante).

Bueno, ¿y qué tal intentar algo equilibrado? (Que no es lo mío, aclaro). Puedo intentar algo...

¿Que qué es un ifstream?
Una especialización para chars de la clase templatre basic_ifstram.
https://en.cppreference.com/w/cpp/io/basic_ifstream

¿No está claro?
Es una clase para hacer simple lo que de otro modo puede resultar más complejo. Es la idea de ser "de alto nivel" de los lenguajes.
std::ifstream es una clase que presenta de una manera simplificada (de alto nivel) la forma de acceder a un archivo como "flujo de entrada". Así, se puede leer en un archivo como si se estuviera usando "cin" (el flujo de caracteres de la entrada estándar).

    std::ifstream entrada("archivo_de_entrada.txt");
    int i;
    double d;
    entrada >> i >> d;


¿Es así de simple?
Casi, también se puede sobrecargar el operador >> para tipos definidos por uno (el programador usuario de la clase), y hacer que la lectura de nuestras propias estructuras de datos sea así de fácil.

¿Sin trampas?
Por supuesto que hay trampas, muchísimas, como todo lo complejo que es fácil de usar, yo no puedo construir mi propia bicicleta pero puedo usarla, más o menos.

¿Qué es un istream_iterator?
Es un iterador de entrada capaz de acceder sucesivamente a los elementos en un "flujo de entrada" (un "input stream", como ifstream o cin).
https://en.cppreference.com/w/cpp/iterator/istream_iterator

¿En dónde se usan?
Comúnmente en algoritmos de la biblioteca estándar que acceder a conjuntos de información por medio de "input iterators" como parámetros.

¿Se pueden usar en código más artesanal para acceder a los elementos de un ifstream, por ejemplo?
Sí, por supuesto, pero pierde toda la gracia.



digimikeh

Dungeons & dragons;
dragons.Attack();