`new int;` 中的 `new` 是否被视为运算符?

Is `new` in `new int;` considered an operator?

int * x = new int; 中的表达式 new int;new expression. The term "new operator" seems to be used interchangeably with "new expression", for example in this question : Difference between 'new operator' and 'operator new'?

新表达式中使用的关键字 new 是运算符是否正确?为什么或为什么不?

如果不是,是否还有其他理由将新表达式称为“新运算符”?

我找不到关于什么是运算符的权威定义。

我已经理解了为对象分配内存的 operator new 和最终可能调用 operator new.

的“新表达式”之间的区别

虽然我知道您正在寻找语义答案,但就我的观点而言,我会说它是一个“关键字”(因为它显然是保留的),而且我假设我们都知道它只是 C++ 的内存分配结构.也就是说,当我想到 C++ 的“运算符”时,我倾向于想到具有可以针对特定类型覆盖的集合 input/output 的函数。 new 对于所有类型都是一样的(更令人困惑的是它可以被覆盖)。

不确定官方 cppreference 是多少,但是:

The new-expression allocates storage by calling the appropriate allocation function. If type is a non-array type, the name of the function is operator new. If type is an array type, the name of the function is operator new[]

https://en.cppreference.com/w/cpp/language/new

看来 new <type> 是分配内存的表达式,而 new 是该表达式的运算符。

使用相同的逻辑:

  • sizeof 是表达式 sizeof(<type>) 的“运算符”(尽管 sizeof 是“compile-time”运算符,与我们使用的有点不同到)
  • + 是表达式 <type> <operator> <type>
  • 的运算符
  • throw 是表达式 throw <throwaable>
  • 的运算符

我只会称它为 new expression 以避免与 void* operator new ( std::size_t count ) 混淆,后者仅在 new expression[=] 过程中分配内存22=] 发票(分配内存,开始生命周期,调用构造函数)。

new 的问题在于它不仅仅调用 operator new。这有点令人困惑,因为对于 x + y+ 仅调用 operator +

Is it correct to say that the keyword new as it is used in a new-expression is an operator? Why or why not?

没有。 new-expression 中的 new 是标识 new-expression.

的关键字

A new-expression 调用一个operator newoperator new[]来获取存储空间。它还会初始化该存储,如果初始化抛出 de-allocates 它(使用 operator deleteoperator delete[])。

有一个明显的区别,因为 operator new 仅被称为 可重载 user-replaceable 函数,而 new-expression 不仅仅是调用这个函数。

参考:7.6.2.8/10[expr.new]

A new-expression may obtain storage for the object by calling an allocation function ([basic.stc.dynamic.allocation]). If the new-expression terminates by throwing an exception, it may release storage by calling a deallocation function. If the allocated type is a non-array type, the allocation function's name is operator new and the deallocation function's name is operator delete. If the allocated type is an array type, the allocation function's name is operator new[] and the deallocation function's name is operator delete[].


通过反例考虑,我们定义了两者

T operator+(T, T);
void* T::operator new(std::size_t);

对于某些类型的 T,然后以任一形式添加:

T a, b;
T c = a + b;
T d = T::operator +(a, b);

完全相同。中缀符号只是运算符调用的语法糖。

然而,分配的行为非常不同:

T *p = new T;
// does much more than
void *v = T::operator new(sizeof(T));

所以调用new-expression语法糖来调用operator new是不合理的。因此,new 关键字不仅仅是选择要调用的函数。不可能,要不然就不得不提到可能也被调用的operator delete函数。

这由 [expr.new], which clearly differentiates between a new-expression and how a new expression may obtain storage by means of calling an allocation function, which is named operator new. Particularly, from [expr.new]/8 [强调 我的]:

A new-expression may obtain storage for the object by calling an allocation function ([basic.stc.dynamic.allocation]). If the new-expression terminates by throwing an exception, it may release storage by calling a deallocation function. If the allocated type is a non-array type, the allocation function's name is operator new and the deallocation function's name is operator delete. If the allocated type is an array type, the allocation function's name is operator new[] and the deallocation function's name is operator delete[].


Is it correct to say that the keyword new as it is used in a new expression is an operator?

特别是 [expr.new]/4 的示例,尽管 non-normative 将此函数描述为运算符函数; "[...] new 运算符":

[...] Instead, the explicitly parenthesized version of the new operator can be used [...]

没有

嗯,是的,因为有人认为 new int 中的 new 是运算符。然而,这个观点(大部分)与标准不一致。

首先,[lex.operators/1] 列出了语言中的运算符。也不要误以为这些只是“预处理运算符”;在 词法 运算符的意义上不存在这种区别。这也没有意义,因为您不能(例如)++ 宏。

new 实际上是一个 关键字 (根据 [lex.key/1])。

接下来,让我们看看new-expression本身。这是事情变得有点毛茸茸的地方。例如[expr.new/4]中有如下写法:

Instead, the explicitly parenthesized version of the new operator can be used to create objects of compound types

我认为这是一个编辑错误,因为它与上面提供的定义不一致,并且在该部分的其他任何地方都没有出现。

然后我们来到运算符重载。在运算符声明的语法生成中,终端列表事物(包括 new)被命名为 operator[over.oper.general/1]). I don't think we need to worry about this. The names of terminals in the grammar have never been intended to introduce definitions of terms. After all, you have and-expression that _doesn't need to be a bitwise AND operation; it can just be an equality-expression:

and-expression:
   equality-expression
   and-expression & equality-expression

像这样定义语法很常见,当然这并不意味着每个 equality-expression 都以某种方式被视为按位 AND 运算符的调用。

最后,一些人声称以下措辞(也在运算符重载部分)证明 new 现在以某种方式孤立地神奇地成为运算符:

The operators new[], delete[], (), and [] are formed from more than one token

我对他们说,不仅 new 甚至没有列出,而且这显然是在更广泛的“可以重载的事物”的意义上使用术语“运算符”,即使 new 本身 仍然不是运算符 。它也在 non-normative 注释中,它应该告诉你所有你需要知道的。

而且,正如您自己指出的那样,我们已经将 operator new 视为其他东西。

new in new int 不被视为运算符。它也不被认为是不是运算符。

关于 'operator' 的构成,C++ 标准非常模糊,甚至不一致。当列出运算符时(如在词法分析和预处理期间定义的那样),它将它们与“标点符号”(如 ( 之类的东西)一起列出,但从来没有真正给出任何标点符号的一般规则。它将 new 列为关键字和运算符。它在关键字集中列出了 sizeof 但在运算符集中没有列出,但后来将其称为运算符。

这里的要点是 C++ 标准委员会并不过分关注将词法世界分为“运算符”和“non-operators”。这是因为实际上没有任何必要。没有适用于所有运算符或所有 non-operators 的语法规则。重要的集合,如overloadable operators 的集合,单独给出;二进制算术表达式之类的语法规则一次给出一个。

基本上,“运算符”不是一个对 C++ 语言有正式意义的类别,因此任何明确的答案都将基于它的“感觉”。如果你愿意,你可以称它为运算符,但你也可以称它为关键字(或标点符号!),语言标准不会与你不一致。