【问题标题】:What is the difference between the dot (.) operator and -> in C++? [duplicate]C++ 中的点 (.) 运算符和 -> 有什么区别? [复制]
【发布时间】:2010-11-17 08:08:54
【问题描述】:

点(.)运算符和C++中的->有什么区别?

【问题讨论】:

    标签: c++ operators


    【解决方案1】:

    foo->bar()(*foo).bar() 相同。

    由于*. 运算符的绑定强度,上述括号是必需的。

    *foo.bar() 不起作用,因为首先评估点 (.) 运算符(请参阅operator precedence

    点 (.) 运算符不能重载,箭头 (->) 运算符可以重载。

    点 (.) 运算符不能应用于指针。

    另见:What is the arrow operator (->) synonym for in C++?

    【讨论】:

    • 请注意,这仅适用于原始指针。对于重载运算符的类类型,它还有一些其他有趣的属性...
    • 难道 -> 是一个向下钻取运算符,因此如果重载它不等于取消引用对象 (*boo).foo 的成员?好像 boo->foo 可能被重载以返回一个中间代理对象,该对象的 foo 成员与原始类中的成员不同。那 assert( (*boo).foo == boo->foo ) 不会失败。确实应该谨慎,因为c++精灵可能潜伏在黑暗中。
    【解决方案2】:

    对于指针,我们可以使用

    *pointervariable.foo
    

    . 运算符的优先级高于* 运算符,因此首先计算.。所以我们需要用括号强制它:

    (*pointervariable).foo
    

    但是一直键入 () 很困难,因此他们开发了-> 作为表达相同内容的快捷方式。如果您正在访问对象的属性或对象引用,请使用. 如果您正在通过指针访问对象的属性,请使用->

    【讨论】:

      【解决方案3】:

      点运算符不能重载,箭头运算符可以重载。箭头运算符通常用于指针(或行为类似指针的对象,如智能指针)。点运算符不能应用于指针。

      编辑 当应用于指针箭头运算符时,相当于将点运算符应用于指针,例如ptr->field 等价于(*ptr).field

      【讨论】:

      • 虽然间接操作符(*foo)可以重载
      【解决方案4】:

      箭头运算符类似于点,但它首先取消引用指针。 foo.bar() 在对象foo 上调用方法bar()foo->bar 在指针foo 指向的对象上调用方法bar

      【讨论】:

      • 如果事物不是指针怎么办?
      • @juanchopanza 如果foo 不是指针并且它的类型是MyType,你会得到一个编译异常:base operand of '->' has non-pointer type 'MyType'
      • @horcrux C++ 允许重载operator->
      • @juanchopanza 但这是一个关于“C++ 中的点 (.) 运算符和 ->”如何工作的通用问题,而不是关于运算符重载的问题。
      • @horcrux 这些运算符在 C++ 中的工作方式必须考虑运算符重载。没有这个,图片就很不完整了。
      【解决方案5】:

      . 运算符用于直接成员访问。

      object.Field
      

      箭头取消引用一个指针,以便您可以访问它指向的对象/内存

      pClass->Field
      

      【讨论】:

        【解决方案6】:
        pSomething->someMember
        

        等价于

        (*pSomething).someMember
        

        【讨论】:

          【解决方案7】:

          目标。 dot 作用于物体;箭头作用于指向对象的指针。

          std::string str("foo");
          std::string * pstr = new std::string("foo");
          
          str.size ();
          pstr->size ();
          

          【讨论】:

            【解决方案8】:

            当你有指针时使用->。 当你有结构(类)时使用.

            当你想指向属于结构的属性时使用.:

            structure.attribute
            

            当您想通过指针指向具有内存引用的属性时,请使用->

            pointer->method;
            

            或相同:

            (*pointer).method
            

            【讨论】:

              【解决方案9】:

              请注意,-> 运算符不能用于某些事情,例如访问 operator[]。

              #include <vector>
              
              int main()
              {
                 std::vector<int> iVec;
                 iVec.push_back(42);
                 std::vector<int>* iVecPtr = &iVec;
              
                 //int i = iVecPtr->[0]; // Does not compile
                 int i = (*iVecPtr)[0]; // Compiles.
              }
              

              【讨论】:

              • 显然不是。因为“foo->”并不意味着“(*foo)”。它的意思是“(*foo)。”。它也不能用于加法、减法... ;)
              • 我不明白这有什么关系。 member[0] 也没有任何意义,但是如果适用,语法糖会将其转换为 member.operator[](0)。值得注意的是 -> 不会让你做大多数人通常期望能够做的事情。
              • 关于那个运算符,我的意思是。
              • 我想 iVecPtr->operator[](0) 会起作用。关键是您站点的语法糖将 [0] 变成 .operator[](0);它不会把 .[0] 变成 .operator[](0)。
              【解决方案10】:

              很简单,只要你看到

               x->y
              

              知道是一样的

               (*x).y
              

              【讨论】:

              • 除非不是,比如->重载的时候。
              • 当你重载时 -> 你也应该重载 * 使得这种关系成立。否则,无论如何都会引入各种混乱。
              【解决方案11】:

              -> 只是指针解引用的语法糖,

              正如其他人所说:

              指针->方法();

              是一种简单的说法:

              (*指针).method();

              如需更多指针乐趣,请查看 Binky 和他的解引用魔杖:

              http://www.youtube.com/watch?v=UvoHwFvAvQE

              【讨论】:

                【解决方案12】:

                两者之间最简单的区别是“->”在查看对象字段、函数等之前取消引用指针,而“.”不首先取消引用。当您有指向对象的指针时使用“->”,并使用“。”当您使用对象的实际实例时。

                另一种等效的写法可能是先在指针上使用取消引用的“*”,然后再使用“.”。我们使用“->”跳过中间人。

                还有其他差异,但其他答案已经广泛涵盖了这一点。

                如果您有 Java 的背景,这可能会让您感到困惑,因为在 Java 中,一切都是指针。这意味着没有理由让符号不首先取消引用您的指针。然而,在 c++ 中,你必须更加小心地记住什么是指针,什么不是指针,最好用前缀“p_”或简单地“p”来标记它们。

                【讨论】:

                  【解决方案13】:

                  . (点)运算符通常用于从类的实例(或类的静态字段/方法)中获取字段/调用方法。

                  p.myField, p.myMethod() - p 类的实例

                  ->(箭头)运算符用于从类指向的内容中获取字段/调用方法。

                  p->myField, p->myMethod() - p 指向一个类

                  【讨论】:

                    【解决方案14】:

                    当我们使用指针时使用 -> 运算符,否则使用点。 所以如果我们有一个像这样的结构类:

                    struct class{ int num_students; int yr_grad; };
                    

                    我们有一个类* curr_class(类指针)的实例,然后要访问我们要做的学生数量

                    cout << curr_class->num_students << endl;
                    

                    如果我们有一个简单的类对象,比如 class_2016,我们会这样做

                    cout << class_2016.num_students << endl;
                    

                    对于指向类的指针,-> 操作符等价于

                    (*obj).mem_var
                    

                    注意:对于一个类,访问该类的成员函数的方式也会是一样的

                    【讨论】:

                      猜你喜欢
                      • 2016-04-28
                      • 2011-01-02
                      • 2012-12-19
                      • 2016-06-22
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-06-24
                      • 2012-09-09
                      相关资源
                      最近更新 更多