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 ) { 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 inferiorlimite superiorincremento){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 "="
string s="hola";
int x=5; 

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) {} } 

 

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

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

Made with Slides.com