En la reunión de estándares 2016 de Oulu ISO C ++, el comité de estándares votó una propuesta llamada Variables en línea en C ++ 17.
En términos simples, ¿qué son las variables en línea, cómo funcionan y para qué sirven? ¿Cómo deben declararse, definirse y utilizarse las variables en línea?

const.inlinepalabra clave para las funciones. Lainlinepalabra clave, cuando se aplica a las funciones, tiene otro efecto crucial, que se traduce directamente en variables. Unainlinefunción, que presumiblemente se declara en un archivo de encabezado, no dará como resultado errores de "símbolo duplicado" en el momento del enlace, incluso si el encabezado obtiene#included por múltiples unidades de traducción. Lainlinepalabra clave, cuando se aplica a las variables, tendrá el mismo resultado exacto. El fin.inlinees solo una solicitud débil y no vinculante para el optimizador. Los compiladores son libres de no solicitar funciones en línea y / o de funciones que no haya anotado. Más bien, el propósito real de lainlinepalabra clave es eludir múltiples errores de definición.Respuestas:
La primera oración de la propuesta:
El efecto garantizado de
inlineaplicado a una función es permitir que la función se defina de forma idéntica, con enlaces externos, en múltiples unidades de traducción. Para la práctica, eso significa definir la función en un encabezado, que se puede incluir en varias unidades de traducción. La propuesta extiende esta posibilidad a las variables.Entonces, en términos prácticos, la propuesta (ahora aceptada) le permite usar la
inlinepalabra clave para definir unaconstvariable de alcance del espacio de nombres de enlace externo , o cualquierstaticmiembro de datos de clase, en un archivo de encabezado, de modo que las múltiples definiciones que resultan cuando ese encabezado se incluye en múltiples unidades de traducción están bien con el enlazador, solo elige una de ellas.Hasta e incluyendo C ++ 14, la maquinaria interna para esto ha estado allí, con el fin de admitir
staticvariables en las plantillas de clase, pero no había una forma conveniente de usar esa maquinaria. Había que recurrir a trucos comoDesde C ++ 17 en adelante, creo que uno puede escribir solo
... en un archivo de encabezado.
La propuesta incluye la redacción
... lo que permite que lo anterior se simplifique aún más a solo
... como señaló TC en un comentario a esta respuesta.
Además, el
constexprespecificador implica tantoinlinepara miembros de datos estáticos como para funciones.Notas:
¹ Para una función
inlinetambién tiene un efecto indirecto sobre la optimización, que el compilador debería preferir reemplazar las llamadas de esta función con la sustitución directa del código de máquina de la función. Esta sugerencia puede ser ignorada.fuente
Kath::hi) no tienen que ser constantes.constrestricción se ha eliminado por completo.static std::string const hi = "Zzzzz...";?Las variables en línea son muy similares a las funciones en línea. Indica al vinculador que solo debe existir una instancia de la variable, incluso si la variable se ve en varias unidades de compilación. El vinculador debe asegurarse de que no se creen más copias.
Las variables en línea se pueden usar para definir globales en bibliotecas de encabezado solamente. Antes de C ++ 17, tenían que usar soluciones alternativas (funciones en línea o hacks de plantillas).
Por ejemplo, una solución alternativa es usar el singleton de Meyer con una función en línea:
Hay algunos inconvenientes con este enfoque, principalmente en términos de rendimiento. Las soluciones de plantilla podrían evitar esta sobrecarga, pero es fácil equivocarse.
Con variables en línea, puede declararlo directamente (sin obtener un error de enlazador de definición múltiple):
Además de las bibliotecas de encabezado solamente, existen otros casos en los que las variables en línea pueden ayudar. Nir Friedman cubre este tema en su charla en CppCon: Lo que los desarrolladores de C ++ deben saber sobre los globales (y el enlazador) . La parte sobre las variables en línea y las soluciones comienza a los 18m9s .
Para resumir, si necesita declarar variables globales que se comparten entre las unidades de compilación, declararlas como variables en línea en el archivo de encabezado es sencillo y evita los problemas con soluciones alternativas anteriores a C ++ 17.
(Todavía hay casos de uso para el singleton de Meyer, por ejemplo, si desea explícitamente tener una inicialización diferida).
fuente
Ejemplo ejecutable mínimo
Esta increíble característica de C ++ 17 nos permite:
constexpr: ¿Cómo declarar constexpr extern?main.cpp
notmain.hpp
notmain.cpp
Compilar y ejecutar:
GitHub aguas arriba .
Ver también: ¿Cómo funcionan las variables en línea?
C ++ estándar en variables en línea
El estándar C ++ garantiza que las direcciones serán las mismas. C ++ 17 N4659 borrador estándar 10.1.6 "El especificador en línea":
cppreference https://en.cppreference.com/w/cpp/language/inline explica que si
staticno se proporciona, entonces tiene un enlace externo.Implementación variable en línea de GCC
Podemos observar cómo se implementa con:
que contiene:
y
man nmdice acerca deu:entonces vemos que hay una extensión ELF dedicada para esto.
Pre-C ++ 17:
extern constAntes de C ++ 17, y en C, podemos lograr un efecto muy similar con un
extern const, lo que conducirá a que se use una única ubicación de memoria.Los inconvenientes
inlineson:constexprcon esta técnica, soloinlinepermite eso: ¿Cómo declarar constexpr extern?main.cpp
notmain.cpp
notmain.hpp
GitHub aguas arriba .
Pre-C ++ 17 encabezado solo alternativas
Estos no son tan buenos como la
externsolución, pero funcionan y solo ocupan una única ubicación de memoria:Una
constexprfunción, porqueconstexprimplicainlineyinlinepermite (fuerza) que la definición aparezca en cada unidad de traducción :y apuesto a que cualquier compilador decente alineará la llamada.
También puede usar una variable entera
constoconstexprestática como en:pero no puede hacer cosas como tomar su dirección, o de lo contrario se usará odr, vea también: https://en.cppreference.com/w/cpp/language/static "Miembros estáticos constantes" y Definiendo datos estáticos constexpr miembros
C
En C la situación es la misma que C ++ pre C ++ 17, he subido un ejemplo en: ¿Qué significa "estático" en C?
La única diferencia es que en C ++,
constimplicastaticpara globales, pero no en C: C ++ semántica de 'static const' vs 'const`¿Alguna forma de alinearlo completamente?
TODO: ¿hay alguna forma de alinear completamente la variable, sin usar memoria alguna?
Muy parecido a lo que hace el preprocesador.
Esto requeriría de alguna manera:
Relacionado:
Probado en Ubuntu 18.10, GCC 8.2.0.
fuente
inlineno tiene casi nada que ver con la alineación, ni para funciones ni para variables, a pesar de la palabra misma.inlineno le dice al compilador que inserte nada en línea. Le dice al enlazador que se asegure de que solo haya una definición, que tradicionalmente ha sido el trabajo del programador. Entonces, "¿Alguna forma de alinearlo completamente?" es al menos una pregunta completamente no relacionada.