Programación en
C++11
por Sebastian Tabares
TODAS LAS AUDIENCIAS
El CONTENIDO siguiente ha sido aprobado para
así que no entres en pánico si eres nuevo en C++
que problemas hay en
C++ < C++11
molestias innecesarias en el código
mucho detalle en la especificación
no hay soporte a multithreading
no tiene "recolector de basura"
C++ < C++11 ?
C++ es estándar deste 1998
ISO/IEC 14882:1998
informalmente C++98
Una corrección en 2003
ISO/IEC 14882:2003
C++03
Y un reporte técnico en 2007
ISO/IEC 19768:2007
C++TR1
"library Technical Report 1"
13 Años después de C++98
nuevas funciones super cool
mejora de rendimiento
escribir código mas rápido
lenguaje mas usable
pero no, todavia no tiene soporte "recolector de basura" :(
8 Funciones super
COOL
Deducción automática de tipo:
auto
en C++03 hay que especificar el tipo de objeto o variable cuando se declara:
#1
int a = 12;
char algo = 'algun texto';
double b = 0.5;
long b = 10000000000000;
C++11 permite declarar objetos sin especificar su tipo:
auto x = 0; // x es de tipo int porque 0 es int
auto c = 'a'; // char
auto d = 0.5; // double
auto deuda = 14400000000000LL; // long long
Esto es realmente útil cuando el tipo de objeto es ampliado o cuando se genera automáticamente
Ejemplo Plantillas
void func(const vector &vi)
{
vector::const_iterator ci=vi.begin();
}
void func(const vector &vi)
{
auto ci = vi.begin ();
}
Esto:
Por esto:
usar auto significa
usar menos código
excepto declarando un tipo int que es una letra menos
y es mas simple escribir cosas repetitivas
“ La palabra clave auto no es nueva, sino que en realidad se remonta a la época pre-C ANSI. Sin embargo, C++11 ha cambiado su significado; auto ya no designa un objeto con tipo de almacenamiento automático. Más bien, se declara un objeto cuyo tipo es deducible de su inicialización ”
auto no puede ser usado en el retorno de una función
pero puede inferir el tipo según los parámetros:
auto suma(auto a,auto b){
return a+b;
}
auto suma(2, 3); //suma es de tipo int
auto suma(2 , 3.14); //suma ahora es de tipo double
Funciones Lambda
Una función lambda es una función que se puede escribir en línea en el código fuente (por lo general para pasar a otra función)
[closure] (parametros) -> tipo-de-retorno {cuerpo}
#2
[closure] define qué variables serán visibles dentro de la lambda.
[var1,var2]
se pasan dos variables (solo lectura)
[&var3]
una variable (como referencia)
[&]
todas las variables como referencia
[=]
todas las variables solo lectura
[ &total, factor ]( int n ) { total += n*factor; };
Por ultimo se puede añadir -> tipo-de-retorno
para forzar el tipo de salida
[&](int n) -> long {total += n*factor;};
int total = 0;
int factor = 3;
[&total,factor](int n) {total = total + n*factor;};
cout << total << endl; // Salida: 15
Ejemplos:
#include <iostream>
using namespace std;
int main()
{
auto func = [] () { cout << "Hola mundo"; };
func(); //ahora se llama a la función
}
#include <iostream> using namespace std; int main() { auto a=1; auto b=2; auto d = [&](int c)-> int {cout << a+b+c;};d(5); //retorna 8 }
Ejemplos:
#include <algorithm> #include <iostream> using namespace std; int main() { char s[]="Hola Mundo!"; int Mayuscula = 0; //modificado por lambda for_each(s, s+sizeof(s), [&Mayuscula] (char c) { if (isupper(c)) Mayuscula++; }); cout << "Hay " << Mayuscula<<" letras mayusculas en: "<< s << endl; }
#3
Bucle for basado en rango
es una caracteristica que ahora comparte con C#, java, python, etc
normalmente el bucle for en C++03 se hace de esta forma:
for(limite inferior; limite superior; incremento){codigo}
int a=0;int a=0;
int arreglo[5]={1,2,3,4,5};
for(int i=0; i<5; i++){
a=a+arreglo[i];
cout << a << endl;
}//imprime 0,1,3,6,10,15
este for es dependiente de i que es el indice del arreglo
¿pero si no sé el numero elementos que tiene el arreglo?
en C++11 también se puede usar:
for(&variable : arreglo){codigo}
int arreglo[5]={20,48,-6,45,0};
for(int &i : arreglo){
cout << i << endl;
} //imprime 20,48,-6,45,0
Operador decltype
Este operador permite mostrar el tipo de dato de una expresión que se le entrega como parámetro
decltype(expresión) -> tipo de dato
#4
Estructura:
función
función main
#include <iostream>using namespace std; struct carro { int capacidadTanque; char* marca; }; carro miCarro() { carro mio; mio.capacidadTanque=10; mio.marca="Ferrari"; return mio; } int main() { auto a = miCarro(); cout<<a.marca; cout<<a.capacidadTanque; return 0; }
C++11 permite deducir el tipo de dato de una expresión y asignarselo a otro objeto:
decltype(3+5) a; //se declara b de tipo int
decltype (3.44) b; //se declara c de tipo double
decltype('h') c; //se declara d de tipo char
decltype(b) d; //se declara d de tipo double
string algo="hola mundo"; //defino un string
decltype(algo.size()) c; //se declara e de tipo int
Iniciacion uniforme
C++11 permite la inicializacion de tipo que trabaja sobre cualquier objeto
#5
Formas de inicializar variables en C++
Inicialización con paréntesis:
string s("hola");
int m=int();
Inicialización con paréntesis:
string s("hola");
int m=int(); inicialización con "="
string s="hola";
int x=5;
inicialización con "="
string s="hola";
int x=5; inicialización con llaves
int arre[4]={1,2,3,4};
struct a hoy={0};
inicialización con llaves
int arre[4]={1,2,3,4};
struct a hoy={0}; inicializacion de constructores
class C {
int x;
S(): x(0) {} }
inicializacion de constructores
class C {
int x;
S(): x(0) {} } Esto es confuso, y puede llegar a ser ambiguo...
int a {3}; //declaro una variable
int b[4] { 1, 2, 0, -1}; //declaro un arreglo
char c[] {"hola mundo"}; //declaro un arreglo de caracteres
int* d = new int[3] { 1, 2, 0 }; //declaro un puntero a un arreglo
int a {3}; //declaro una variable
int b[4] { 1, 2, 0, -1}; //declaro un arreglo
char c[] {"hola mundo"}; //declaro un arreglo de caracteres
int* d = new int[3] { 1, 2, 0 }; //declaro un puntero a un arreglo
al declarar variables y arreglos:
C++11 permite
En clases y sus instancias:
#include <iostream> using namespace std; class C { int a; int b; public: C(int i, int j): a(i), b(j) {}; int suma(){ return a+b; } }; int main() { C c {3,2}; //C++11. Equivalente a: C c(3,2); cout<<c.suma(); //devuelve 5 return 0; }
En constructores de clases:
class X {
int a[4];
public:
X() : a {1,2,3,4} {} //inicializando el arreglo(miembro de la clase)
};
En contenedores:
ya se puede dejar atrás la lista interminable de push_back()
cambiar esto:
vector<string> vs;
vs.push_back("primero");
vs.push_back("segundo");
vs.push_back("tercero");
por esto:
vector<string> vs={ "primero", "segundo", "tercero"};
#6
C++11 soporta iniciacion de los miembros dentro de la misma clase
class C
{
int a=7; //solo en C++11
public:
C();
};
#7
nullptr como nuevo tipo de valor nulo
NULL
nullptr
0
VS
VS
VS
se pueden declarar punteros nulos de la siguiente forma:
el valor nulo '0' y NULL hacen una conversión implícita a un entero:
bool a = 0; //nulo o cero
int b = 2;
int c = NULL; //lo convierte en cero
cout<<(b+c); //devuelve 2
int* p1 = NULL;
int* p2 = nullptr;
int* p3 = 0;
if(p1==p2) {cout<<"son iguales"<<endl;}
if(p2==p3) {cout<<"son iguales tambien"<<endl;}
bool f = nullptr; //ok
int i = nullptr; // error: un nullptr nativo solo puede ser convertido a bool o, usando reinterpret_cast, a un tipo entero
nullptr tiene la peculiaridad:
nullptr reemplaza a la macro NULL muy propensa a bugs, y claro, tambien a 0.
#8
Librería estándar C++11
Agrega varias nuevas bibliotecas para expresiones regulares, nuevas clases de contenedores, tuplas, funciones contenedoras objeto y más.
Nuevas clases de contenedores
nuevos algoritmos
Uso de all_of()
all_of(inicio rango,fin rango,funcion())
tambien sirve para any_of() y none_of()
#include <iostream> #include <algorithm> #include <array> using namespace std; int main () { array<int,8> arr {3,5,7,11,13,17,19,23}; if ( all_of(arr.begin(), arr.end(), [](int i){return i%2;}) )cout<<"Todos son impares"; return 0; }
Uso de copy_n()
copy_n(iterador de entrada,n primeros elementos,iterador de salida)
#include <algorithm>
int entrada[5] {0,12,34,50,80};
int salida[5];
//copia los primeros 5 elementos de entrada a salida
copy_n(entrada,5,salida);
Uso de iota()
iota(iterador,iterador+n,inicio de iteracion)
#include <numeric>
int b[5] {0}, c[10], i {100};
char d[3] {0};
iota(b, b+5, 10); //cambia 'b' a {10,11,12,13,14}
iota(d, d+3, 'a'); //{'a','b','c'}
iota(c,c+100,i); //cambia 'c' a {100,101,102,103,104,105,106,107,108,109}
Gracias
Programación enC++11
By Sebastian Yesid Tabares Amaya
Programación enC++11
características útiles en C++11
- 1,617