Una buena regla general es para cualquier cosa que necesite comparar en la condición de bucle contra algo que es naturalmente un std::size_t
sí mismo.
std::size_t
es el tipo de cualquier sizeof
expresión y, como se garantiza, puede expresar el tamaño máximo de cualquier objeto (incluida cualquier matriz) en C ++. Por extensión, también se garantiza que sea lo suficientemente grande para cualquier índice de matriz, por lo que es un tipo natural para un bucle por índice sobre una matriz.
Si solo cuenta hasta un número, entonces puede ser más natural usar el tipo de la variable que contiene ese número o un int
o unsigned int
(si es lo suficientemente grande) ya que estos deberían ser de un tamaño natural para la máquina.
size_t
cuando debería puede conducir a errores de seguridad .ssize_t
valores firmados.size_t
es el tipo de resultado delsizeof
operador.Se usa
size_t
para variables que modelan el tamaño o el índice en una matriz.size_t
transmite semántica: inmediatamente sabe que representa un tamaño en bytes o un índice, en lugar de simplemente otro entero.Además, usar
size_t
para representar un tamaño en bytes ayuda a hacer que el código sea portátil.fuente
El
size_t
tipo está destinado a especificar el tamaño de algo, por lo que es natural usarlo, por ejemplo, obtener la longitud de una cadena y luego procesar cada carácter:Usted no tiene que estar atento a las condiciones de contorno, por supuesto, ya que es un tipo sin signo. El límite en el extremo superior no suele ser tan importante ya que el máximo suele ser grande (aunque es posible llegar allí). La mayoría de las personas simplemente usan un
int
para ese tipo de cosas porque rara vez tienen estructuras o matrices que se vuelven lo suficientemente grandes como para exceder la capacidad de esoint
.Pero ten cuidado con cosas como:
lo que causará un bucle infinito debido al comportamiento de ajuste de los valores sin signo (aunque he visto que los compiladores advierten sobre esto). Esto también puede ser aliviado por el (un poco más difícil de entender pero al menos inmune a los problemas de envoltura):
Al cambiar el decremento a un efecto secundario posterior a la verificación de la condición de continuación, esto verifica la continuación del valor antes del decremento, pero aún usa el valor decrementado dentro del bucle (por lo que el bucle se ejecuta en
len .. 1
lugar delen-1 .. 0
).fuente
strlen
a cada iteración de un bucle. :) Puedes hacer algo como esto:for (size_t i = 0, len = strlen(str); i < len; i++) ...
for (size_t i = strlen (str); i --> 0;)
-->
operador "va a" (ver stackoverflow.com/questions/1642028/… ). Han incorporado su sugerencia en la respuesta.if (i == 0) break;
al final del bucle (por ejemplo,for (size_t i = strlen(str) - 1; ; --i)
(I como la suya mejor sin embargo, pero sólo me preguntaba si esto funcionaría igual de bien)..Por definición,
size_t
es el resultado delsizeof
operador.size_t
fue creado para referirse a los tamaños.La cantidad de veces que haces algo (10, en tu ejemplo) no se trata de tamaños, entonces ¿por qué usarlo
size_t
?int
ounsigned int
debería estar bien.Por supuesto, también es relevante lo que haces
i
dentro del bucle. Si lo pasa a una función que tomaunsigned int
, por ejemplo, pickunsigned int
.En cualquier caso, recomiendo evitar las conversiones de tipo implícito. Haga explícitas todas las conversiones de tipo.
fuente
size_t
es una forma muy legible de especificar la dimensión de tamaño de un elemento: longitud de una cadena, cantidad de bytes que ocupa un puntero, etc. También es portátil en todas las plataformas: encontrará que 64 bits y 32 bits se comportan bien con las funciones del sistema ysize_t
- algo queunsigned int
podría no hacer (por ejemplo, cuándo debe usarunsigned long
fuente
respuesta corta:
casi nunca
respuesta larga:
Siempre que necesite tener un vector de carbón más grande que 2 gb en un sistema de 32 bits. En cualquier otro caso de uso, usar un tipo con signo es mucho más seguro que usar un tipo sin signo.
ejemplo:
El equivalente firmado de
size_t
esptrdiff_t
, noint
. Pero el usoint
sigue siendo mucho mejor en la mayoría de los casos que size_t.ptrdiff_t
estálong
en sistemas de 32 y 64 bits.Esto significa que siempre debe convertir ay desde size_t cada vez que interactúa con un std :: container, lo que no es muy bonito. Pero en una conferencia nativa en curso, los autores de c ++ mencionaron que diseñar std :: vector con un size_t sin signo fue un error.
Si su compilador le da advertencias sobre conversiones implícitas de ptrdiff_t a size_t, puede hacerlo explícito con la sintaxis del constructor:
si solo desea iterar una colección, sin límites, utilice el rango basado en:
aquí algunas palabras de Bjarne Stroustrup (autor de C ++) al volverse nativo
Para algunas personas, este error de diseño firmado / no firmado en el STL es motivo suficiente para no utilizar el std :: vector, sino una implementación propia.
fuente
for(int i = 0; i < get_size_of_stuff(); i++)
. Ahora, claro, es posible que no quieras hacer muchos bucles sin procesar, pero, vamos, también los usas.x + 1 < y
equivalente ax < y - 1
, pero no están con enteros no genéricos. Eso puede introducir errores fácilmente cuando se transforman cosas que se supone que son equivalentes.Use std :: size_t para indexar / contar matrices de estilo C.
Para los contenedores STL, tendrá (por ejemplo)
vector<int>::size_type
, que debe usarse para indexar y contar elementos vectoriales.En la práctica, generalmente son ints sin signo, pero no está garantizado, especialmente cuando se usan asignadores personalizados.
fuente
std::size_t
generalmente esunsigned long
(8 bytes en sistemas de 64 bits) en lugar deunisgned int
(4 bytes).size_t
embargo, las matrices de estilo C no están indexadas , ya que los índices pueden ser negativos. Sin embargo, se podría usarsize_t
para la propia instancia de dicha matriz si no se quiere ser negativo.+
en punteros, parece queptrdiff_t
es el que se debe usar para los índices.vector<T>::size_type
(y lo mismo ocurre con todos los otros contenedores), en realidad es bastante inútil, porque está garantizado efectivamente que essize_t
- está tipificadoAllocator::size_type
, y para restricciones sobre eso con respecto a los contenedores, ver 20.1.5 / 4 - en particular,size_type
debe sersize_t
ydifference_type
debe serptrdiff_t
. Por supuesto, el valor predeterminadostd::allocator<T>
cumple esos requisitos. Así que usa el más cortosize_t
y no te molestes con el resto del lote :)Pronto, la mayoría de las computadoras serán arquitecturas de 64 bits con SO de 64 bits que ejecutan programas que operan en contenedores de miles de millones de elementos. A continuación, se debe utilizar
size_t
en lugar deint
como índice del bucle, de lo contrario su índice va a envolver alrededor de la 2 ^ 32: ésimo elemento, tanto en sistemas de 32 y 64 bits.¡Prepárate para el futuro!
fuente
long int
lugar de unint
. Sisize_t
es relevante en un sistema operativo de 64 bits, era igual de relevante en un sistema operativo de 32 bits.Cuando use size_t tenga cuidado con la siguiente expresión
Obtendrá falso en la expresión if, independientemente del valor que tenga para x. Me tomó varios días darme cuenta de esto (el código es tan simple que no hice la prueba de la unidad), aunque solo me llevó unos minutos determinar el origen del problema. No estoy seguro de que sea mejor hacer un lanzamiento o usar cero.
Ambas formas deberían funcionar. Aquí está mi prueba de funcionamiento
La salida: i-7 = 18446744073709551614 (int) (i-7) = - 2
Me gustaría los comentarios de otros.
fuente
(int)(i - 7)
trata de un flujo inferior que se convierteint
después, mientrasint(i) - 7
que no es un flujo inferior ya que primero conviertei
a anint
, y luego resta7
. Además, encontré su ejemplo confuso.size_t es devuelto por varias bibliotecas para indicar que el tamaño de ese contenedor no es cero. Lo usas cuando regresas: 0
Sin embargo, en el ejemplo anterior, hacer un loop en size_t es un error potencial. Considera lo siguiente:
El uso de enteros sin signo tiene el potencial de crear este tipo de problemas sutiles. Por lo tanto, prefiero usar size_t solo cuando interactúo con contenedores / tipos que lo requieren.
fuente
size_t
es un tipo sin signo que puede contener el valor entero máximo para su arquitectura, por lo que está protegido contra desbordamientos de enteros debido al signo (el signo int0x7FFFFFFF
incrementado en 1 le dará -1) o el tamaño corto (el signo corto sin signo int 0xFFFF incrementado en 1 le dará 0).Se utiliza principalmente en indexación de matrices / bucles / aritmética de direcciones, etc. Funciones como
memset()
y por igualsize_t
solo aceptan , porque teóricamente puede tener un bloque de memoria de tamaño2^32-1
(en la plataforma de 32 bits).Para tales bucles simples, no se moleste y use solo int.
fuente
size_t es un tipo integral sin signo, que puede representar el número entero más grande en su sistema. Úselo solo si necesita matrices muy grandes, matrices, etc.
Algunas funciones devuelven un size_t y su compilador le avisará si intenta hacer comparaciones.
Evite eso utilizando el tipo de datos firmado / sin firmar apropiado o simplemente escribiendo para un hack rápido.
fuente
size_t es unsigned int. así que cuando quieras int sin firmar puedes usarlo.
Lo uso cuando quiero especificar el tamaño de la matriz, el contador ect ...
fuente
size_t
puede ser un entero de 64 bits sin signo, mientras que en una máquina de 32 bits es solo un entero sin signo de 32 bits.