【问题标题】:Are . and -> in C and C++ really operators?是 。和 -> 在 C 和 C++ 中真的是运算符吗?
【发布时间】:2010-11-28 01:26:14
【问题描述】:

你可能一直很坚强,你自己很坚强,那个。和 -> 是运算符,用于检索结构 (C) 或类 (C++) 的成员。

但是,我怀疑它们是运算符 - 因为,如果它们是运算符,它们的输入类型是什么?此外,两边的标识符是相互依赖的——例如 + 运算符所缺乏的特性。

如果这是正确的——在什么意义上这些在实践中仍然被标记为运算符,它们在语言理论方面的正式定义是什么。

【问题讨论】:

    标签: c++ c programming-languages operators


    【解决方案1】:

    您假设唯一可以作为参数传递给运算符的类型是可以在语言中定义的类型。

    我认为编译器可以识别的任何类型都可以作为参数传递,包括诸如“标识符”之类的内部类型。运算符在其 AST 表示中将有两个参数,这足以让您定义语义。

    另一个论点是语言理论可能会为你的词汇提供一组定义,但它不是唯一的。

    例如,操作员可能是操作机器的人。该定义与编程理论无关,但它不会阻止我使用特定领域语言中的关键字来表达与机器操作有关的内容。类似地,“算子”一词在数学中的定义比特定于编程理论的定义更广泛——而且该定义不会因为使用编程语言而失效。

    换一种说法——如果你不称它为运营商,你会怎么称呼它

    编辑

    为了澄清,我的第一个论点是指使用运算符(调用)的语法。这些运算符具有正确的参数,它们是标识符 - 成员名称 - C++ 语言无法使用数据类型表示。 C++ 语言确实有成员指针,但它们与成员不同——就像变量与指向该变量的指针不同一样。

    我认为这就是问题所指的内容。这些运算符的正确参数的类型无法在语言中正常表达或操作。

    当该语法映射到重载的operator-> 函数时会发生什么情况是另一回事。函数不是操作符——它只是操作符的实现方式。

    【讨论】:

      【解决方案2】:

      我认为您可以使用“operator”关键字重载-> 运算符这一事实应该是一个死的赠品。

      智能指针经常这样做:

      template<class T>
      struct myPtr {
          T *operator ->()    { return m_ptr; }
      
          private:
              T *m_ptr;
      };
      

      . 不可重载,但根据定义也是一个运算符。

      【讨论】:

        【解决方案3】:

        嗯...sizeof是一个运算符,它的输入类型是什么?我不认为这个问题对于在这种情况下区分运营商和非运营商有用。

        将是因为“运算符”在编程语言的上下文中的含义正是该语言的作者它的意思是。刘易斯卡罗尔的阴影在这里。

        【讨论】:

        • 当然,在编程理论术语中,sizeof 更可能被认为是一个函数。在编译时而不是运行时采取行动是不重要的。成为编译器内在函数而不是用户/库函数不是重点。事实上,参数类型是“数据类型”——一种你不能作为参数传递给你自己的函数的类型——也不是重点,无论 sizeof 是一个函数还是一个运算符。 C 和 C++ 的标准和行话给出了具有自己历史的替代定义,但即使是 Lewis Carroll 也在开一个与 Cratylus 相关的笑话。
        • 顺便说一句 - 我仍然给你 +1 以供 Lewis Carroll 参考。与我的小分歧非常相关。
        • @Steve314:“函数”的这种定义(包括sizeof)似乎与运算符的定义略有不同——+ 运算符同样可以称为“函数” "。
        • @caf - + 运算符在语法上是中缀。当然,您可以使用前缀运算符,但是一旦您开始按字母顺序拼写它们,通常的术语(特定的 C/C++ 术语除外)往往是“函数”。在 sizeof 的情况下,你甚至有强制的括号,这(在模糊的绝对不是教堂所说的意义上)倾向于暗示一个功能。
        • @Steve314:带有sizeof 的括号只有在对类型名称进行操作时才需要 - 给定int array[10];,那么sizeof array 是完全有效的。将运算符和函数之间的区别归结为是否使用字母字符拼写似乎有点似是而非。
        【解决方案4】:

        该参考资料说它们都是 C++ 中的运算符:

        http://www.cplusplus.com/doc/tutorial/operators/

        这还不够权威吗?

        【讨论】:

        • 谢谢,是的。同样的问题也可以用于例如类型转换、范围解析,标准将其视为运算符。尽管如此,我仍然对没有函数原型的运算符感到不舒服。
        • 正如我在另一条评论中所说的 - 诉诸权威是一个被广泛认可的无效论点。 C++ 标准委员会和参与定义该语言的人可能错误地选择了他们的话。在这种情况下,他们没有这样做,但仍有空间解释为什么该措辞是恰当的,而不是仅仅说“某某这么说”。
        • @Steve314:不,当你诉诸一个实际上并没有定义答案的权威时,诉诸权威只是一个无效的论据。 C++ 标准定义了 C++ 语言中什么是运算符,什么不是运算符,不管运算符在其他地方是什么或意味着什么。
        • @Steve314:operator 一词的意思是 C++ 中特定的东西。因此,判断某物是否是 C++ 中的运算符的唯一方法是查看定义,在这种情况下,它是标准。这不是诉诸权威——这确实是一个谬误——而是“诉诸定义”,这在同义反复中是正确的。您可能会争辩说该规范的作者应该选择另一个术语(尽管我不同意),但您最多只能说“C++ 对 operator 的定义很糟糕”。 (如果您随后争辩说 operator 在其他地方的含义相同,则适用于向当局提出上诉。)
        • @Antal - 当然,任何实质性文档都需要自己的行话特定定义。没关系。但是这里的问题专门引用了编程理论中的正式定义,这些定义不会因为我们谈论的是由具有特定术语的特定文档定义的特定语言而无效。对于某些问题,诉诸标准是完全有效的,但在这种情况下,IMO 毫无意义。最好解释一下为什么字词的选择不是坏事或误导。
        【解决方案5】:

        您可以重载 -> 运算符:Wikipedia。该页面还指出您不能超载点。有一个例子 -> 重载here:

        class String // this is handle
        {
          ...
          Stringrep *operator -> () const { return b_; }
          private:
          Stringrep *b_;
        }
        

        箭头作用于箭头左侧的值,并返回左侧“保持在内部”的任何值。想想smart pointer

        【讨论】:

          【解决方案6】:

          C++03 标准将两者都称为运算符。

          例子:

          ...在 .运算符应用于其类类型的表达式...

          如果您对该术语不满意,您可以将术语标点符号用于.

          【讨论】:

            【解决方案7】:

            在线 C 标准 (n1256):

            6.5.2.3 结构和联合成员

            约束

            1 . 运算符的第一个操作数应具有合格或不合格的结构或联合 类型,第二个操作数应命名该类型的成员。

            2 -&gt; 运算符的第一个操作数的类型应为“指向合格或不合格的指针” 结构”或“指向合格或不合格联合的指针”,第二个操作数应 命名指向类型的成员。

            它们是运算符,它们的输入类型由标准指定。

            【讨论】:

              【解决方案8】:

              哈哈,我知道人们已经绕圈说了这句话,只是直接说出来。在 C 语言中,label-> 实际上是 (*label) 的简写。 。话虽如此, 。是引用结构中元素的运算符。因此,-> 在指向结构的指针中引用一个元素。

              【讨论】:

              • 在 C 术语中是的,但标签包括 C++。重载时,operator-&gt;operator* 分开,因此“速记”参数不一定适用。也就是说,确保速记有效地应用仍然是一种好习惯 - 如果您重载 operator-&gt;operator*,您应该一致地重载它们(并牢记预期的类似指针的语义)。
              • 是的,我说的是 c 术语。但是,我确实认为在 C++ 中重载 -> 是非常糟糕的做法。
              • 我同意,真的。由于智能指针和迭代器通常只实现 operator*,因此会出现一些不一致。如果 -> 只是一种简写方式 - 在有意义时始终可用,并且不需要 operator-> - 它会避免一些麻烦。
              猜你喜欢
              • 2010-12-03
              • 2016-10-27
              • 2010-10-15
              • 1970-01-01
              • 2016-07-12
              • 1970-01-01
              • 2010-12-11
              相关资源
              最近更新 更多