对象之间的差异->function()和object.function()

Difference between object->function() and object.function() in C++

本文关键字:function object gt 之间 对象      更新时间:2023-10-16

有人能解释一下做之类的事情之间的区别吗

a->height();

a.height();

真的有区别吗?

在第一个示例中,a是指向对象的指针,在第二个示例中是对象本身(或对对象的引用)。在最低层次上,两者之间没有明显的区别。

这是一个奇怪的问题,假设我们谈论的是内置的->。这听起来有点像"锤子和苹果有什么区别"。通常,当两种变体至少在某种程度上可互换时,就会出现关于"差异"的问题,两者同时适用。因此,人们会询问"差异"来决定使用哪种变体。这里的情况并非如此。

a->height()a.height()不能同时有效。根据a的类型,两者中只有一个是有效的。也就是说,你无法选择使用哪个版本。如果左侧是指向对象的指针,则第一个(带有->)适用。第二个(只有.)仅适用于左侧为对象值本身的情况。所以,这就是它的全部。

->只是一元*.的组合的简写,这意味着当a是指针时,a->height()等效于(*a).height()。因此,一个更合理的问题是a->height()(*a).height()之间的差异。答案是:没有区别(同样,只要我们考虑内置的->

它基本上可以归结为您如何声明"a"。如果你这样做:

SomeClass a;

那么"a"本身就是一个对象,您可以使用"."来引用其成员。

如果你这样做:

SomeClass * a;
a = [some expression that produces a pointer to a SomeClass object];

则"a"是指向对象的指针,而不是对象本身。然后使用"->"表示法。

(上述规则有一些潜在的例外,但大多数人都不会遇到。)

还值得一提的是,一些对象(如智能指针)支持这两种符号。在这种情况下,第一个将引用指针所指向的对象,第二个将引用智能指针本身。

operator->后面跟着一个函数调用,将导致返回的指针被取消引用,并在结果对象上调用函数。简而言之,a->foo()(*a).foo()的简写。

除了a->foo()需要a作为定义foo的类的指针这一正确答案之外,一个人为的例子可能会告诉我们一些不同的东西:

struct xC {
   struct Member {
      void foo(){printf("xC::Member::foon");};
   };
   Member a;
   Member* operator->() { return &a; }
   // following function doesn't really make sense.
   void foo() { printf("xC::foon");};
};
int main(){
    xC x;
    x.foo(); // prints "xC::foo".  
    x->foo();// prints "xC::Member::foo"
}

在智能指针和stl迭代器的上下文中,您经常会看到这些类型的operator->定义。在这种情况下,定义确实遵循了Stroustrup的指导方针,不要像我的例子那样滥用它来做一些违反直觉的事情,而是让定义类像"指向"某个对象一样可用。

假设a是指向某个对象的指针,则:

此:

a->height();

只是的简写

(*a).height();

它允许您通过指针而不仅仅是普通对象(或引用)来调用方法
实际上,您不需要使用->版本,但当您将几个调用链接到一起时,它的用处就显而易见了。

person->body()->arm(right)->hand()->finger(index)->ring()->activate();

如果你写这个长手,它是:

(*(*(*(*(*(*person).body()).arm(right)).hand()).finger(index)).ring()).activate();

很难将取消引用(*)与正在取消引用的指针关联起来。而第一个版本->左边的东西是一个指针,右边的东西是指针被取消引用后的对象部分。

正如其他人所说,如果你谈论的是指针的去引用,那么差异不会太大。然而,更重要的是,如果a是一个实例或引用,并且定义了operator->函数,那么您可能会看到非常不同的行为。a.name()会调用a的name()函数,而a->name()可能会调用其他类型的name()函数以及该类决定要做的任何其他工作(这是一个返回指针的函数调用,因此"邪恶"类只要返回有效指针,就可以做它想做的任何事情)。这主要用于智能指针,但在语言中不能保证这一点。

这一切都可以归结为代码本身的可读性和速度。在汇编程序的最低级别,它可以归结为推/拉堆栈。在当今拥有快速计算机/MCU的现实生活中,这并不重要。这是你使用的编程风格。两种方法都可以,但不要混合使用。这可能会让其他程序员很难阅读。