任何人都可以解释做类似的事情之间的区别:
a->height();
和
a.height();
真的有区别吗?
In the first example a is a pointer to an object, in the second example it is the object itself (or a reference to the object). At the lowest level, there is no clear difference between the two.
这是一个奇怪的问题,假设我们谈论的是内置的->
. 这听起来有点像“锤子和苹果有什么区别”。通常,当两个变体至少在某种程度上可以互换,两者同时适用时,就会出现关于“差异”的问题。因此,人们会询问“差异”来决定使用哪个变体。这不是这里的情况。
您不能同时拥有两者a->height()
和a.height()
有效。两者中只有一个是有效的,具体取决于a
. 即,您无法选择使用哪个版本。->
如果左侧是指向对象的指针,则第一个(带有 a )适用。第二个(只有 a .
)仅适用于左侧是对象值本身的情况。所以,这就是它的全部。
The->
只是一元*
and组合的简写.
,这意味着 whena
是一个指针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”是指向对象的指针,而不是对象本身。然后使用“->”符号。
(上述规则有一些潜在的例外,但它们不是大多数人遇到的。)
还值得一提的是,像智能指针这样的一些对象同时支持这两种表示法。在这种情况下,第一个将引用指针指向的对象-第二个将引用智能指针本身。
假设这a
是一个指向某个对象的指针,那么:
这个:
a->height();
只是以下的简写:
(*a).height();
它允许您通过指针调用方法,而不仅仅是普通对象(或引用)。
您实际上不需要使用 -> 版本,但是当您将几个调用链接在一起时,它为什么有用就很明显了。
person->body()->arm(right)->hand()->finger(index)->ring()->activate();
如果你写这个长手,它是:
(*(*(*(*(*(*person).body()).arm(right)).hand()).finger(index)).ring()).activate();
很难将取消引用 (the *
) 与它正在取消引用的指针相关联。虽然第一个版本 -> 左边的东西是一个指针,右边的东西是指针被取消引用后的对象部分。
,operator->
后跟函数调用,将导致返回的指针被取消引用,并在结果对象上调用函数。简而言之,a->foo()
是 的简写(*a).foo()
。
除了a->foo()
需要a
指向类定义的指针的正确答案之外foo
,一个人为的例子可能会说明一些不同的东西:
struct xC {
struct Member {
void foo(){printf("xC::Member::foo\n");};
};
Member a;
Member* operator->() { return &a; }
// following function doesn't really make sense.
void foo() { printf("xC::foo\n");};
};
int main(){
xC x;
x.foo(); // prints "xC::foo".
x->foo();// prints "xC::Member::foo"
}
在智能指针和 stl 迭代器的上下文中,您经常会看到这些类型的operator->
定义。在这种情况下,定义确实遵循 Stroustrup 的指导方针,不要滥用它来做一些违反直觉的事情,比如我的例子,而是让定义类像“指向”某个对象一样可用。
As others have said, if you are talking about the dereferencing of a pointer, then the difference would not be terribly significant. More importantly however, if a
is a instance or a reference and has defined an operator->
function then you could see very different behaviors. a.name()
would call a's name()
function while a->name()
could be calling some other type's name()
function along with any other work the class has decided to do (it is a function call returning a pointer so 'evil' class could do most anything it wants so long as it returns a valid pointer). This is primarily used for smart pointers, but there is no guarantee of that in the language.
这一切都归结为您希望代码本身的可读性以及您希望它有多快。在汇编程序的最低级别,它归结为推/拉堆栈。在当今使用快速计算机/MCU 的现实生活中,这并不重要。这是您使用的编程风格。两种方式都可以,但不要混合使用。这会使其他程序员难以阅读。