La expresión new int;
como en int * x = new int;
es una nueva expresión . El término "nuevo operador" parece usarse indistintamente con "nueva expresión", por ejemplo en esta pregunta: ¿ Diferencia entre 'nuevo operador' y 'operador nuevo'?
¿Es correcto decir que la palabra clave new
tal como se usa en una nueva expresión es un operador? ¿Por qué o por qué no?
Si no es así, ¿existe otra justificación para llamar a una nueva expresión "nuevo operador"?
Tengo problemas para encontrar una definición autorizada de lo que constituye un operador.
Ya entiendo la distinción entre el operador nuevo que asigna memoria para un objeto y "nueva expresión" que eventualmente puede llamar a un operator new
.
c++
language-lawyer
François Andrieux
fuente
fuente
new
es comosizeof
aquí. Y creo que la mayoría de la comunidad de C ++ piensasizeof
en un operador. El stansard incluso se refiere al "sizeof
operador" cuando describe sus efectos.sizeof
, yo diría que sería el operador de una expresiónsizeof(<type>)
. Y+
es un operador para una expresión unaria<type> <op> <type>
. Esa es mi conclusión / interpretación al menos, siéntete libre de corregirme.new
es un operador o no, hay una diferencia entre una expresión y un operador. Por ejemplo,new int
es una expresión que se evalúa como algo. Sinew
se considera un operador, entonces sólo la parte "nueva" denew int
es el operador (es decir, es su propia cosa separada). Conceptualmente, un operador es algo que actúa sobre otra cosa.Respuestas:
new
innew int
no se considera un operador. Tampoco se considera que no sea un operador.El estándar C ++ es realmente vago, e incluso inconsistente, sobre lo que constituye un 'operador'. Cuando se enumeran los operadores (como se define durante el lexing y el preprocesamiento), los enumera junto con los "puntuadores" (cosas como
(
), pero nunca da realmente ninguna regla para los puntuadores en general. Se enumeranew
como palabra clave y como operador. Se enumerasizeof
en el conjunto de palabras clave pero NO en el conjunto de operadores, pero luego se refiere a él como un operador.La conclusión aquí es que el comité de estándares de C ++ no está demasiado preocupado por separar el mundo léxico en "operadores" y "no operadores". Esto se debe a que realmente no es necesario. No hay reglas gramaticales que se apliquen a todos los operadores o no a todos los operadores. Los conjuntos importantes, como el conjunto de operadores sobrecargables , se proporcionan por separado; Las reglas gramaticales para cosas como expresiones aritméticas binarias se dan una a la vez.
Básicamente, "operador" no es una categoría que sea formalmente significativa para el lenguaje C ++, por lo que cualquier respuesta categórica se basará en cómo se "siente". Puede llamarlo operador si lo desea, pero también puede llamarlo una palabra clave (¡o un puntuador!) Y el estándar de idioma no estará en desacuerdo con usted.
fuente
operator
y me imagino que, cuando alguien pide una delimitación exacta, es justo usar la palabra en inglés "operador" para las cosas que funcionan con esa palabra clave. En ese sentido,new
,new[]
,delete
,delete[]
,co_await
, algunos typecasts, y conversiones de literales definidos por el usuario a los objetos serían operadores.operator
palabra clave e incluyen cosas como.
que no se pueden usar con laoperator
palabra clave. Si me vieran forzado a punta de pistola a dar una definición de "operador", mi mente no iría a "operador sobrecargable".operator
palabra clave, sí. Si me viera obligado a encontrar una delimitación absolutamente precisa de lo que es o no un operador, optaría por lo único que está definido con precisión en la gramática. En la comunicación diaria, no necesitaría tanta precisión todo el tiempo.No. En
new
una nueva-expresión es una palabra clave que identifica una nueva-expresión .Una nueva expresión llama una
operator new
ooperator new[]
para obtener almacenamiento. También inicializa ese almacenamiento y lo desasigna (conoperator delete
ooperator delete[]
) si la inicialización arroja.Hay una clara distinción, ya que
operator new
solo se la conoce como una función reemplazable por el usuariosobrecargable, y una nueva expresión hace más que simplemente llamar a esta función.Referencia: 7.6.2.8/10
[expr.new]
Considere, a modo de contraejemplo, que definimos tanto
T operator+(T, T); void* T::operator new(std::size_t);
para algún tipo T, luego suma en cualquiera de las formas:
T a, b; T c = a + b; T d = T::operator +(a, b);
es idéntico. La notación infija es simplemente azúcar sintáctica para la llamada del operador.
Sin embargo, la asignación se comporta de manera muy diferente:
T *p = new T; // does much more than void *v = T::operator new(sizeof(T));
por lo que no es razonable llamar al azúcar sintáctico de nueva expresión para llamar a
operator new
. Por lo tanto, lanew
palabra clave no es simplemente seleccionar la función a llamar. No puede ser, o tendría que mencionar laoperator delete
función que también se podría llamar.fuente
operator new
Es un operador sobrecargable", ¿verdad? Yo no lo creo:operator +
no es un operador sobrecargable -+
es, y que defino sobrecargas por medio de una función de llamadaoperator +
.new
palabra clave tal como aparece en una nueva expresión.new
esté sujeto a la sobrecarga del operador sugiere que la respuesta debería ser sí ,new
(en sí mismo) es un operador.Solo lo llamaría nueva expresión para evitar confusiones con lo
void* operator new ( std::size_t count )
que solo asigna memoria como parte del proceso que factura la nueva expresión (memoria de asignación, vida útil inicial, constructor de llamada).El problema con
new
es que hace más que simplemente llamar aloperator new
. Lo cual es un poco confuso porque es parax + y
las+
únicas llamadasoperator +
.fuente
Esto se rige por [expr.new] , que diferencia claramente entre una nueva expresión y cómo una nueva expresión puede obtener almacenamiento mediante la llamada a una función de asignación , que se nombra
operator new
. En particular, de [expr.new] / 8 [ énfasis mío]:En particular, el ejemplo, aunque no normativo, de [expr.new] / 4 describe esta función como una función de operador; "[...] el
new
operador" :fuente
No.
Bueno, algo sí, en el sentido de que existen personas que se consideran
new
ennew int
ser un operador. Sin embargo, esta opinión está (en su mayoría) en desacuerdo con el estándar.En primer lugar,
[lex.operators/1]
enumera los operadores en el idioma. No se deje engañar pensando que estos son simplemente "operadores de preprocesamiento"; no existe tal distinción en el sentido de operadores léxicos . Tampoco tendría sentido, ya que no puede (por ejemplo)++
una macro.new
es, de hecho, una palabra clave (por[lex.key/1]
).A continuación, veamos la nueva expresión en sí. Aquí es donde las cosas se ponen un poco más confusas. Hay, por ejemplo, la siguiente redacción en
[expr.new/4]
:Considero que esto es un error editorial, ya que está en desacuerdo con las definiciones proporcionadas anteriormente y no ocurre en ningún otro lugar de esa sección.
Luego llegamos a la sobrecarga del operador . En su producción gramatical para una declaración de operador, el terminal que enumera cosas (incluido
new
) se denomina operador ([over.oper.general/1]
). No creo que debamos preocuparnos por esto. Los nombres de terminales en la gramática nunca han tenido la intención de introducir definiciones de términos. Después de todo, tiene una expresión and que _no necesita ser una operación AND bit a bit; puede ser simplemente una expresión de igualdad :Es común definir gramáticas como esta, y ciertamente no significa que cada expresión de igualdad deba considerarse de alguna manera una invocación del operador AND bit a bit.
Finalmente, algunos han afirmado que la siguiente redacción (también en la sección de sobrecarga del operador) es una prueba de que de
new
alguna manera ahora, de forma aislada, mágicamente es un operador:A ellos les digo, no sólo no está
new
ni siquiera en la lista, sino que está claramente usando el término "operador" en el sentido más amplio de "cosas que se pueden sobrecargar", aunquenew
en sí mismo todavía no es un operador . También está en una nota no normativa, que debería decirle todo lo que necesita saber.Y, como usted mismo señala, ya lo consideramos
operator new
otra cosa.fuente
sizeof
es un operador. [expr.throw] es menos explícito con respecto a,throw
pero todavía habla de un "operando"throw
, lo que implica quethrow
es un operador.Si bien sé que está buscando una respuesta semántica, en lo que a opinión respecta, diría que es una "palabra clave" (ya que está claramente reservada), y supongo que ambos sabemos que es simplemente la construcción de C ++ para la asignación de memoria. Dicho esto, cuando pienso en los "operadores" de C ++, tiendo a pensar en funciones con una entrada / salida establecida que se puede anular para tipos específicos. new es el mismo para todos los tipos (y, lo que es más confuso, puede anularse).
No estoy seguro de cuán oficial es cppreference, pero:
https://en.cppreference.com/w/cpp/language/new
Parece seguirse entonces que
new <type>
es una expresión para asignar memoria, mientras quenew
es el operador para esa expresión.Usando esa misma lógica:
sizeof
es un "operador" para la expresiónsizeof(<type>)
(aunquesizeof
es un operador de "tiempo de compilación", un poco diferente de lo que estamos acostumbrados)+
es un operador para una expresión<type> <operator> <type>
throw
es un operador para la expresiónthrow <throwaable>
fuente
[]()
también es un operador? Esfor
? Esthrow
?[]
y()
constituiría operadores separados. Nuevamente,for
es absolutamente una palabra clave, pero donde delimitaría ser un operador fue la primera parte de poder ser anulado. Técnicamente, por eso,sizeof
no es un operador, lo cual es cierto en C ++ en el sentido de que es más una expresión de preprocesamiento. Ythrow
es un operador de una expresiónthrow <throwable>
[]()
a la combinación al definir una lambda. Pero su respuesta también es interesante porque (en C ++) la respuesta depende del contexto: infoo()
,()
es un operador (¡sobrecarga!); en(1 + 2)
él no es un operador en absoluto (en algunos otros lenguajes, notablemente R, esto es diferente). De todos modos, el criterio anulable no es suficiente. Hay un montón de cosas en C ++ que son los operadores sin ambigüedades pesar de no ser sobrecargable (.
,::
,:?
, ambossizeof
s, etc).[]()
como una lambda es una bestia difícil de definir (específicamente porque no estoy tan al día con mi C ++). Así que aquí todavía diría que[]
()
constituyen operadores diferentes de una expresión lambda , pero no estoy seguro de si argumentaría que no se pueden anular, o si el mismo acto de implementar / declarar una lambda constituye anular la lambda básica (como en Java). El diseño del lenguaje comienza a convertirse en un arte sobre la ciencia allí. En cuanto a( ... )
, es un separador en la mayoría de los idiomas que he usado, pero echaré un vistazo a R muy rápido(a + b)
es semánticamente idéntica a la llamada de función `(` (a + b), o, de hecho, `(` (`+` (a, b)), donde `x` puede usarse para hacer un nombrex
se ajusta sintácticamente a una llamada de función en lugar de especial (como un operador infijo).