C++
es un lengueaje de propósito general, el nuevo estándar centra sus
esfuersos en dos aspectos fundamentales:
Hacer
a c++ un mejor lenguaje para la programación de sistemas y creación
de biliotecas.
Hacer a c++ más fácil de enseñar y aprender.
Hay
muchas aplicaciones en las que podemos encontrar a c++ unas
veces como lenguaje principal y otras veces usado en partes críticas
de las mismas ej:
Google, el motor de búsqueda.
Amadeus, para venta de voletos de vuelo.
Facebook, la red social.
JVM (Oracle).
Interpretes javascrip (google V8).
Qt, framework para el desarrollo multiplataforma.
POCO, para el desarrollo orientado a la web.
OpenCV, para el tratamiento en tiempo real de imágenes.
Navegadores
Web (Internet Explorer, Mozilla, Google-Chrome, Safari).
En
general se pueden encontrar muchas aplicaciones en finansa,
telecomunicaciones, drivers, el ejército,
aplicaciones embebidas, videojuegos, matemática computacional(para
lo que no fue originalmente creado, sin
embargo está siendo ampliamente utilizado),
robótica, entre muchas otras.
Como
lo dice el título del post, acá les comparto algo de lo nuevo de
c++11 antiguamente conocido como c++0x (si quieres una referencia más
completa deberás leer un libro, yo recomiendo “The C++
Programming Language . Fourth Edition. Bjarne Stroustrup (el creador
original de C++... que más se puede decir...)”, autores
como estos además te recomiendan para ver material técnico
específico la especificación de la iso(ISO C++ standard
(ISO/IEC 14882-2011) [C++,2011] )).
Bueno
las novedades de c++
abarcan la forma de escribir(sintácsis), el rendiemiento,
facilidades de la biblioteca estandar,
entre otras, de manera general son bastantes los cambios(a mi
concideración para bien). C++11
salió ya hace algún tiempo: en 2009 se realiza una primera revisión
del estándar a modo de borrador, en agosto de 2011 fue aprobado por
la iso, en 2012 sale la primera implementación completa y hoy
estamos aquí, algunos sin usarlo todavía a pesar de que actualmente
es soportado por gcc(g++), clang, visualc++, por solo mencionar los
compiladores más populares. Resulta que la “inercia” por lo que
conocemos en ocaciones es muy fuerte y hace que nos estanquemos
mientras la tecnología avanza. Yo concidero que un ingeniero no se
debe medir tanto por lo que sabe como por lo que está dispuesto a
aprender, una empresa que contrate un desarrollador o ingeniero en
general que no esté dispusto a seguir los
avances estaría adquiriendo un recurso humano que rapidamente
quedaría sin soporte, es mejor tener un desarrollador LTS(Longer
Time Support, :-P que se adapta a los cambios tecnológicos al pasar
el tiempo).
Para
ver un ejemplo de comparación
del rendimiento(performace) del nuevo c++(c++11) en comparación con
el antiguo(2003 que fue una revisión/corrección del c++
iso 1998) consideremos
el siguiente ejemplo.
std::vector<int>
getInts()
{
std::vector<int>
ints;
for(int
i =0; I <=10000000; i++) ints.push_back(i);
return
ints;
}
Como
podemos ver aquí se está creando un vector de enteros en un ámbito
más
reducido al que probablemente usará
el valor de retorno, en este caso una vez que se tenga en memoria
este vector al retornarlo se llama al constructor de copia
para copiar uno por uno los elementos del vector para retornar esta
copia y eliminar(de forma automática) de la memoria el creado
originalmente, como te podrás dar cuenta tiene poco sentido esto de
que teniendo los datos en meoria se cree una copia, se elimine el
original y el copiado sea el que se use por el simple hecho de
salirse del ámbito(el ámbito es la definición del espacio
de vida de un objeto que puede ser global,
de espacio de nombre, de clase, de función, de bloque, etc). Pués
bien c++11 provee algunas soluciones a esto, una de ellas es la
utilización de el contructor move que en vez de hacer una copia lo
que hace es mover la dirección de memoria del
dato en cuestión y entregarsela al ámbito que hizo el pedido.
Otra
forma de resolver este problema hubiese sido usando un puntero
reservando memoria para él
de forma dinámica y retornando su dirección de memoria, esto en
realidad es una solución implementable pero a la vez es un
antipatrón ya que va en contra del principio de RAII
(‘‘Resource Acquisition Is Initialization’’), o sea si la
memoria se crea en este ámbito quién debería ser el responsable
de eliminarla para mantener este esquema... pués c++11 también
provee
una solución elegante desde esta perpectiva y es con
el uso de shared_ptr
lo que crea un objeto de
propiedad compartida que devolverá la memoria reclamada en cuanto el
último
de sus propietarios lo haga sin tener que llamar de forma explícita
a delete.
Otro
ejemplo es al usar regex(nuevo), si quieres representar una expresión
que incluya algún slash
invertido o comilla doble este debe ser precedido por un backslash(es
a lo que se le llama escapar la cadena).
Por ejemplo al representar lo siguiente:
string
s = "\\w\\\\w";
// I hope I got that right
podemos
darnos cuenta que esto es propenso a errore, para ello el nuevo
c++(c++11) provee raw string literals
en el cual un backslash es un backslash!!!, ej:
string
s = R"(\w\\w)"; // I’m pretty sure I got that right
Otro
ejemplo que me
gustaría
comentar, auto y
range-for:
La
palabra auto ha cambiado el significado de las antiguas versiones
donde la había heredado
de C, antes significaba que la variable era autodestruible, o sea
escribir auto int era
equivalente a int esto
indicaba que el objeto llamaba a su destructor de forma automática
al salirse del ámbito, ahora indica detecció de tipo desde el
inicializador con lo cual podriamos por ejemplo escribir:
template<class
T> void f1(vector<T>& arg)
{
for
(vector<T>::iterator p = arg.begin(); p!=arg.end(); ++p) *p =
7;
for
(auto p = arg.begin(); p!=arg.end(); ++p) ∗p = 7;
}
los
cuales serían equivalentes y por su puesto el segundo más elegante
que el primero.
El
range-for te permite recorrer un contenedor de forma muy sencilla,
tal como sigue:
void
print_book(const vector<Entry>& book)
{
for
(const auto& x : book) cout << x << '\n';
}
esto
no se explica, solo se mira y el código habla por si solo, además
comentar que para tener un contenedor propio capaz de usar esta
cualidad solo hay que implemntar el begin y el end del contenedor.
Como
último ejemplo las expresiones lambda o funciones lambda
(simplemente lambda como también se les suele llamar). Lambda es una
notación simplificada para definir y utilizar objetos o instancias
de funciones anónimas. Esto es particularmente útil cuando pasas
una operación como argumento a un algorimo, aquí puedes ver un
ejemplo:
template<class
C>
void
print_modulo(const C& v, ostream& os, int m)
//
output v[i] to os if v[i]%m==0
{
breadth_first(begin(v),end(v),
[&os,m](int
x) { if (x%m==0) os << x << '\n'; }
);
}
Un
ejemplo de la utilidad de esto lo puedes ver al usar signal/slog(un
concepto de Qt
framework).
Como
podrás saber es imposible tratar en un simple post sobre todas estas
nuevas características por lo que te dejo en manos de Stroustrup:
Here
are what I consider the most widely useful new ‘‘building
bricks’’ affecting the style of
C++11
code with references to the text and their primary authors:
•
Control of defaults: =delete and =default: §3.3.4,
§17.6.1, §17.6.4; Lawrence Crowl and
Bjarne
Stroustrup.
•
Deducing the type of an object from its initializer,
auto: §2.2.2, §6.3.6.1; Bjarne Stroustrup.
I
first designed and implemented auto in 1983 but had to remove it
because of C compatibil-
ity
problems.
•
Generalized constant expression evaluation (including
literal types), constexpr: §2.2.3,
§10.4,
§12.1.6; Gabriel Dos Reis and Bjarne Stroustrup [DosReis,2010].
•
In-class member initializers: §17.4.4; Michael
Spertus and Bill Seymour.
•
Inheriting constructors: §20.3.5.1; Bjarne
Stroustrup, Michael Wong, and Michel Michaud.
•
Lambda expressions, a way of implicitly defining
function objects at the point of their use in
an
expression: §3.4.3, §11.4; Jaakko Jarvi.
•
Move semantics, a way of transmitting information
without copying: §3.3.2, §17.5.2;
Howard
Hinnant.
•
A way of stating that a function may not throw
exceptions noexcept: §13.5.1.1; David Abra-
hams,
Rani Sharoni, and Doug Gregor.
•
A proper name for the null pointer, §7.2.2; Herb
Sutter and Bjarne Stroustrup.
•
The range-for statement: §2.2.5, §9.5.1; Thorsten
Ottosen and Bjarne Stroustrup.
•
Override controls: final and override: §20.3.4.
Alisdair Meredith, Chris Uzdavinis, and Ville
Voutilainen.
•
Type aliases, a mechanism for providing an alias for
a type or a template. In particular, a
way
of defining a template by binding some arguments of another template:
§3.4.5, §23.6;
Bjarne
Stroustrup and Gabriel Dos Reis.
•
Typed and scoped enumerations: enum class: §8.4.1;
David E. Miller, Herb Sutter, and
Bjarne
Stroustrup.
•
Universal and uniform initialization (including
arbitrary-length initializer lists and protec-
tion
against narrowing): §2.2.2, §3.2.1.3, §6.3.5, §17.3.1, §17.3.4;
Bjarne Stroustrup and
Gabriel
Dos Reis.
•
Variadic templates, a mechanism for passing an
arbitrary number of arguments of arbitrary
types
to a template: §3.4.4, §28.6; Doug Gregor and Jaakko Jarvi.
Para
ver un pequeño ejemplo de c++11 en acción revisa: