C++17 (también conocido como C++1z) es el nombre de la versión ISO /IEC del estándar C++. Las especificaciones para C++17 se publicaron en diciembre de 2017 [1] [2] .
El valor de la constante __cplusplusse ha convertido en 201703L, esto se usa para la compilación condicional .
Los trígrafos se utilizaron para máquinas con codificación no estándar y/o teclados limitados. A finales de los años 80, con la difusión de las codificaciones de 8 bits y los teclados de membrana de caucho baratos , los trigrafos perdieron su significado, y treinta años más tarde fueron naturalmente excluidos [3] [4] .
// ¿Se ejecutará la siguiente línea????????????????/ a ++ ; /* con trigraphs esta línea está comentada - trigraph ??/ es equivalente a \ */El lenguaje C era un "ensamblador portátil": permitía hacer programas rápidos que se compilaban en diferentes computadoras, y también usaba utilidades de ensamblador ( enlazador , bibliotecario). Conceptos como " archivo de cabecera " y " unidad de traducción " son ecos de aquellos tiempos.
La palabra registerse asoció originalmente con la optimización manual del programa. Los compiladores modernos "debajo del capó" realizan una gran cantidad de optimizaciones, y ese control manual parece redundante. En C++ 11, la palabra se declaró indeseable. La palabra aún está reservada y es posible que algún día se use para un propósito diferente, como en C++11 [5] . auto
La operación obviamente no es segura y está prohibida en C++98 [6] . --Falta la operación .
Las excepciones declaradas void f() throw(A, B, C);, que se encuentran en Java , por ejemplo, hacen más daño que bien. Prohibido en C++11, eliminado en C++17. Permaneció throw()como sinónimo de noexcept(true)[7] .
Entre ellos se encuentran std::auto_ptrantiguos std::random_shuffleadaptadores funcionales [8] [9] .
En su lugar, unique_ptrse utilizan shuffley nuevas plantillas de funciones basadas en function/ bind. Se afirma que cualquier código en auto_ptrse puede convertir mecánicamente a unique_ptr, con una simple adición std::movedonde hay una transferencia de propiedad.
También se han eliminado partes separadas iostreamprohibidas en C++98 [10] .
Cinco sobrecargas en total, incluida esta.
plantilla < classAlloc > _ function ( std :: allocator_arg_t , const Alloc & alloc ) noexcept ;Debido a la semántica incomprensible y las dificultades de implementación, se eliminaron sin prohibición previa [11] .
Varias características raras de la biblioteca estándar están prohibidas: [12] [13] [14]
Prometen eliminarlos por completo en C++20.
Con la transición a C11, los archivos de encabezado <ccomplex>, <cstdalign>, <cstdbool>, <ctgmath>. El archivo <ciso646>no está prohibido [19] .
El inicializador universal agregado en C ++ 11 int x{};le permite crear un objeto, estructura, matriz con una sintaxis. En C++17, se aclara: si en lugar de un tipo se encuentra , el autousuario quiere crear un objeto y no se necesita initializer_list.
Al mismo tiempo , auto x = {1, 2, 3};continúa creando: por un lado, por compatibilidad con , por otro lado, hay [20] [9]for (auto x : {1, 2, 3}) para un objeto . auto x = 1;
automático x1 = { 3 }; // std::initializer_list<int> auto x2 { 1 , 2 }; // error ahora auto x3 { 3 }; // En tLas funciones y ahora son funciones con diferentes tipos (pero no pueden formar un conjunto sobrecargado). Esto permitirá que la API solicite devoluciones de llamada que no generen excepciones, así como optimizar el código para none [21] . void f() noexcept(true);void f() noexcept(false);
C++11 introdujo la capacidad de crear estructuras de datos cuya alineación es mayor que la teórica. Esta posibilidad fue recogida por la nueva operación [22] .
clase alinea ( 16 ) float4 { flotante f [ 4 ]; }; float4 * p = nuevo float4 [ 1000 ];Hubo una sobrecarga del operador new con un parámetro adicional para asignar correctamente un objeto sobrealineado en la memoria.
Se ha cambiado el significado del concepto prvalue: ahora es solo una inicialización.
Si bien el código SomeType a = 10;aún requiere tanto el constructor como el operador =, solo se garantiza que se llamará al constructor.
Esto significa que las funciones pueden devolver tipos que no se pueden copiar ni mover.
Ahora las operaciones a.b, a->b, a->*b, a(b1, b2, b3), b += a(y análogos para otras operaciones), a[b], a << by a >> bse evalúan en el orden a → b para mantener los efectos secundarios bajo control [23] .
Si se llaman como funciones (por ejemplo, operator += (a, b)), el orden permanece indefinido.
Hay plantillas que aceptan una constante.
plantilla < int N > estructura Matriz { int a [ N ]; };Lo que puede ser una N constante, y lo que no puede - declarado lo contrario. Una constante en una plantilla no puede ser un puntero a un campo, un objeto temporal, un literal de cadena, un resultado typeido una variable estándar __func__[17] [24] ;
Now for (auto v : x)significa , permitiendo inicio y fin de diferentes tipos. auto __begin = begin-expr; auto __end = end-expr;
Esta es la base para iterar a través de los rangos, que es un trabajo en progreso [25] .
Las matrices std::vector y std::string se ocupan de las regiones contiguas de la memoria. Introdujeron el concepto de "iterador continuo" [26] [27] . Conceptualmente, nada ha cambiado.
También dieron definiciones a otros conceptos: referencia de reenvío , inicializador de miembro predeterminado , entidad con plantilla . Este es un trabajo sobre conceptos de C++20 .
Anteriormente, este comportamiento estaba definido por la implementación.
Al mismo tiempo, crearon "caracteres UTF-8" que tienen un tipo y pueden contener códigos del 0 al 127, similares a las cadenas UTF-8, aparentemente, para que el programa dependa menos de la configuración regional de la computadora [ 17] [28] . char
Debido a una semántica inadecuada, se prohibió verbalmente (sin la marca ) el método de pedido “consumir” , exigiendo el uso del método “adquirir”. El trabajo sobre la nueva semántica aún está en curso, y tal vez algún día se levante la prohibición [29] . [[deprecated]]
En cualquier caso, en PowerPC y ARM , todas las descargas consumirán automáticamente , pero no todas adquirirán , y el método de consumo puede ahorrar relojes en código multiplataforma [30] .
Si static_assertno funciona, no siempre es necesario decirle al programador lo que está mal; a menudo, él mismo puede resolverlo a partir del contexto. [31] .
static_assert ( tamaño de ( wchar_t ) == 2 );Ahora puede escribir en el archivo de encabezado y, al incluir este archivo en archivos cpp, todos se referirán al mismo objeto (el constructor de clase no se llamará repetidamente para cada archivo cpp, a diferencia de o ), inline const ClassName INSTANCE_NAMEconst ClassName INSTANCE_NAMEstatic const ClassName INSTANCE_NAME
Defecto del lenguaje C++: en plantillas typenamey en classalgunos lugares no intercambiables [33] .
plantilla < plantilla < nombre de tipo > clase X > estructura C ; // OK plantilla < plantilla < nombre de tipo > nombre de tipo X > struct D ; // no compilaAmbas palabras clave se declaran explícitamente intercambiables.
Ha surgido una nueva forma de declarar variables para desempaquetar objetos complejos, llamada enlace estructural [34] .
auto [ lugar , fueInsertado ] = algúnMapa . emplazar ( clave , valor );Funciona para pares, tuplas y otros tipos donde . std::get
Definición de espacios de nombres anidados: [9] [35] namespace A::B {} como abreviatura de namespace A { namespace B {} };
Por ejemplo:
enumeración clase TriBool { no , tal vez , SÍ , NN [[ tal vez_no usado ]], SIN ESPECIFICAR [[ en desuso ( "Renombrado a QUIZÁS" )]] = QUIZÁS }; constexpr int TriBool_N = static_cast < int > ( TriBool :: NN ); const char * triBoolNames [ TriBool_N ] = { "no" , "tal vez" , "sí" };Todavía no hay un objetivo declarado [17] [36] , pero esto permitirá a los desarrolladores del compilador encontrar uno; por ejemplo, declarar que el elemento NN es especial y no necesita ser asignado a variables procesadas en switch.
El concepto de SFINAE hizo posible crear una plantilla simple enable_ifque brinda una funcionalidad diferente para diferentes tipos, pero proporciona un código pesado. En C++17, puede simplificar el programa: el operador if constexpr(expression)instancia el código si la expresión entre paréntesis es verdadera [37] .
plantilla < claseT > _ constexpr T absoluto ( T arg ) { devolver argumento < 0 ? -arg : arg ; _ } plantilla < claseT > _ constexpr auto precision_threshold = T ( 0.000001 ); plantilla < claseT > _ constexpr bool close_enough ( T a , T b ) { if constexpr ( is_punto_flotante_v < T > ) // << !! return absoluto ( a - b ) < precision_threshold < T > ; más devuelve a == b ; }En este caso, nos aseguramos de que la diferencia entre los números fraccionarios sea pequeña, y los enteros simplemente se verifican por igualdad.
Expresiones empaquetadas [17] [38] :
template < typename ... As > bool foo ( As ... args ) { retorno ( argumentos && ...); }Mantisa hexadecimal y exponente decimal: 0xC.68p+2, 0x1.P-126, similar a la sustitución %a. C admite esta sintaxis desde la versión 99 [39] .
Similar a la inicialización de variables locales en for, hace que el código sea más compacto [40] .
if ( auto it = m . find ( key ); it != m . end ()) return it -> second ;Le permite establecer parámetros de plantilla de cualquier tipo a través de [41] . auto
template < auto X > struct B { static constexpr auto value = X ; }; B < 5 > b1 ; // OK: el tipo de parámetro de plantilla es int B < 'a' > b2 ; // OK: el tipo de parámetro de la plantilla es char B < 2.5 > b3 ; // error: el tipo de parámetro de plantilla no puede ser dobleera: . Se convirtió en: [42] . [self = *this]{ self.f(); }[*this]{ f(); }
enum classa veces se usa para hacer que otro tipo de entero no sea compatible con nada. Ahora las variables de este tipo se pueden inicializar con números [43]
clase de enumeración Manejador : intptr_t { INVÁLIDO = 0 } ; Asa h { 42 }; Mango h = 42 ; // prohibidoA menudo sucede que necesita pasar una cadena sin cambios a otra sección de código, esto se puede hacer usando los siguientes métodos:
void doSmth ( const char * s ); // ¿Qué sucede si hay un carácter nulo en la cadena? Sí, y el interior de la función se vuelve erróneo void doSmth ( const std :: string & s ); // ¿Qué sucede si la cadena no es una cadena y tenemos que asignar memoria?C ++ 17 introdujo un tipo string_view , una cadena que tiene solo un puntero y una longitud, sin propiedad, sin administración de memoria y ni siquiera terminando en nulo, por lo que no tiene una extensión c_str(). Solo se pueden cambiar los bordes (comienzo/longitud), no los caracteres. El trabajo del programador es asegurarse de que el objeto no sobreviva al búfer de memoria donde se almacena la cadena, y pasar parámetros es un gran uso para ello. El objeto string_viewes muy pequeño (máquina de 2 bits) y debe pasarse por valor en lugar de por referencia.
string_viewen sí mismo es una abstracción: abstrae el método de almacenamiento de cadenas y solo requiere una cosa: que los datos de texto sean bytes consecutivos en la memoria. Solo estructuras inusuales complejas (por ejemplo, honda/cuerda ) almacenan cadenas aleatorias. Y todo el resto, y , y y varios tipos de arreglos, se convierten en . stringconst char*string_view
Hay dos nuevas constantes, hardware_constructive_interference_sizey hardware_destructive_interference_size. Por lo tanto, el usuario puede evitar el intercambio falso (interferencia destructiva) y mejorar la localidad (interferencia constructiva).
estructura mantener_apartado { alignas ( hardware_destructive_interference_size ) atomic < int > cat ; alignas ( hardware_destructive_interference_size ) atomic < int > dog ; // el gato está lejos del perro, se pueden cambiar desde diferentes hilos. }; estructura -juntos { atómico < int > perro ; cachorro int ; }; estructura de la perrera { //... alignas ( tamaño de ( juntos )) paquete juntos ; //... }; static_assert ( tamaño de ( juntos ) <= hardware_constructive_interference_size ); // asegúrese de que juntos sean una línea de caché.Teóricamente, ambas constantes deberían ser iguales, pero para soportar arquitecturas heterogéneas, se decidió hacer dos constantes. [cincuenta]
Un mutex que le permite leer en paralelo y escribir en uno [51] . Los bloqueadores para ello se llaman shared_locky unique_lock.
Aparecieron funciones en la biblioteca, las llamadas guías de deducción , que le permiten hacer esto:
std :: par p ( 2 , 4.5 ); // una estándar :: vector < int > v = { 1 , 2 , 3 , 4 }; std :: vector x ( v.begin ( ), v.end ( ) ) ; // 2Para std::mapy std::unordered_mapse han añadido dos nuevas funciones [52] .
#incluir <iostream> #incluir <mapa> par de clase { público : int valor1 , valor2 ; Par () : valor1 ( 0 ), valor2 ( 0 ) {} Par explícito ( int aValue1 ) : value1 ( aValue1 ), value2 ( 0 ) {} Par ( int aValue1 , int aValue2 ) : valor1 ( unValor1 ), valor2 ( unValor2 ) {} }; int principal () { std :: mapa < std :: cadena , Par > m ; // C++11 m [ "a" ] = Par ( 3 , 4 ); m _ emplace ( "a" , 1 ); // Siempre se crea el par // C++ 17m . insert_or_assign ( "a" , Par ( 3 , 4 )); m _ try_emplace ( "a" , 1 ); // El par se crea cuando es necesario devolver 0 ; }Se han introducido funciones matemáticas no estándar en el espacio de nombres estándar: beta, , , , , , , , , , , [53] [54] . No hay ninguno fuera de std (in ). cyl_bessel_i/j/kcyl_neumann[comp_]ellint_1/2/3expinthermite[assoc_]laguerre[assoc_]legendreriemann_zetasph_besselsph_legendresph_neumannmath.h
De la primera oración (2010): "Esperamos que la adopción de esta propuesta envíe un mensaje a las diversas comunidades informáticas de que, a pesar de la creencia popular, C++ también es bastante adecuado para su industria". Luego no fue aceptado. Ahora, los principales proveedores de bibliotecas ( Dinkumware , Boost , GCC ) ya cuentan con estas características.
También se agregó el cálculo de MCD [55] y LCM [56] , la función de reducción al rango ( ) [57] , la hipotenusa tridimensional . clamphypot(x, y, z)
Una biblioteca de sistema de archivos basada en boost::filesystemle permite: [58]
Existía una clase capaz de contener datos de cualquier tipo [59] [60] . Se requieren implementaciones para adaptarse a objetos pequeños sin asignar memoria. La función requiere una coincidencia exacta del tipo y no dará nada si está dentro del archivo . std::anyanyany_castany_cast<double>int
std :: cout << std :: boolalpha ; estándar :: cualquiera a = 1 ; std :: cout << a . tipo (). nombre () << ": " << std :: any_cast < int > ( a ) << std :: endl ; a = 3,14 ; std :: cout << a . tipo (). nombre () << ": " << std :: any_cast < double > ( a ) << std :: endl ; a = verdadero ; std :: cout << a . tipo (). nombre () << ": " << std :: any_cast < bool > ( a ) << std :: endl ; // i: 1 // d: 3.14 // b: verdaderoTambién hay más simples std::variant<int, bool, double>y std::optional<T>.
Un inconveniente conocido de C ++: para la conversión de números a texto de bajo nivel sin asignación de memoria, debe ejecutar uno pesado y poco confiable sprintf, y la conversión integrada de texto a un número que queda con C es bastante poco confiable.
Ahora hay supervelocidades locales independientes incorporadas from_chars[61] y to_chars[62] . Están diseñados de tal manera que no requieren (y no producen) un cero de cierre y pueden funcionar, por ejemplo, en string_view. Debido a sus limitaciones e independencia local, están destinados principalmente a JSON y XML , donde se necesita una gran velocidad.
Las estructuras de datos STL ( cadenas , vectores , etc.) contienen un parámetro de plantilla: un asignador de memoria. Este asignador funciona como un concepto de programación genérico , no como una interfaz orientada a objetos: la asignación de memoria en el montón y el grupo da como resultado diferentes tipos incompatibles. Una clase es un comienzo estándar para una tarea rara: según algunas condiciones, asigna memoria en el montón o en el grupo. polymorphic_allocator
Por sí mismo , no es una interfaz, sino que está asociado a una interfaz . polymorphic_allocatormemory_resource
Permite la llamada consistente de funciones, objetos con el operador () ( funtores ) y objetos lambda [63] . También se agregaron funciones , , . is_invocableis_invocable_rinvoke_result
Para 69 se han inventado algoritmos de , y versiones paralelas [64] [65] [66] . <algorithm><numeric><memory>
lenguaje de programación c | |
---|---|
compiladores |
|
bibliotecas | |
Peculiaridades | |
algunos descendientes | |
C y otros lenguajes |
|
Categoría:Lenguaje de programación C |
C++ | |
---|---|
Peculiaridades | |
algunas bibliotecas | |
compiladores | |
influenciado | |
|