Usar bien const en C y C++
En esta lección vas a usar la palabra clave const para declarar datos de solo lectura y a distinguir las distintas formas de combinar const con punteros.
Introducción
La palabra clave const permite que una función se comprometa a no modificar los datos que recibe. Si alguien modifica por error un dato marcado como const, el compilador avisa del error de inmediato. Así el código es más seguro, y quien lo lee ve fácilmente qué funciones pueden modificar los datos.
Puntos importantes
- Un puntero solo debe apuntar a un objeto que todavía existe, del tipo correcto, o valer null.
- Cada zona de memoria reservada debe liberarse exactamente una vez.
- Deja claro qué función es dueña de la memoria (ownership) y qué datos solo se leen (const).
Ejemplos de código C y C++
#include <stdio.h>
int sum(const int *values, size_t count) {
int total = 0;
for (size_t i = 0; i < count; ++i) total += values[i];
return total;
}
int main(void) {
const int values[] = {2, 4, 6};
printf("%d\n", sum(values, 3));
return 0;
}
12
#include <array>
#include <iostream>
int sum(const std::array<int, 3>& values) {
int total = 0;
for (int value : values) total += value;
return total;
}
int main() {
const std::array values{2, 4, 6};
std::cout << sum(values) << '\n';
}
12
Comparación entre C y C++
El parámetro const int *values indica que la función sum lee los elementos del arreglo sin modificarlos. Lee la declaración empezando por el nombre de la variable: un puntero a datos const (const int *) protege el valor apuntado, mientras que un puntero const (int * const) no puede apuntar a otra dirección. C++ también tiene funciones miembro const, que se comprometen a no modificar el estado del objeto.
La propiedad y la liberación de la memoria dependen por completo del programador.
Los contenedores y RAII liberan automáticamente los recursos cuando el objeto llega al final de su vida.
Ejercicios de práctica
Ejecuta las dos versiones y después modifica el código para ver la diferencia de seguridad que aporta cada lenguaje.
- Prueba con punteros nulos y con fallos al reservar memoria.
- Ejecuta el programa con AddressSanitizer y UndefinedBehaviorSanitizer para detectar errores de memoria.
- Deja claro qué puntero es dueño de la memoria y cuál solo sirve para leer.