在C/C++中,->和.的区别是什么?这个问题的原理是什么?

7

可能重复:
C++: ptr->hello(); /* VERSUS */ (*ptr).hello();
为什么C语言有“->”和“.”的区别?

我知道成员运算符(.)和指针成员运算符(->)之间的区别。

为什么C语言的设计者会创建一个不同的操作符来访问这个?为什么编译器不能自己找出来呢?

如果你总是使用“.”,是否存在任何情况不明确你是指成员还是指指针成员?

编辑:我不是在寻找“(*a).b”语法。我想知道为什么设计者不允许您使用“a.b”而不是“a->b”?


这个符号最初来自于C语言。 - Mark Byers
3
@Greg:那不是完全相同的问题。那个问题问为什么需要 p->x,考虑到它只是 (*p).x 的语法糖。而这个问题问为什么我们不能只使用 p.x 而不是 p->x - James McNellis
这个有点棘手,因为标点符号的缘故很难搜索 - 我使用了数据转储的 grep 命令。 :) - Greg Hewgill
显示剩余4条评论
7个回答

6

你真的希望编译器“自己想出来”吗?如果是这样,那么以下内容将会得到相同的结果(假设p是指向具有成员x的结构体的指针):

(*p).x;
p.x

如果指针的取消引用在那里是隐式的,那么它是否应该隐式地出现在任何地方呢?考虑以下内容:
int* p;
int i = p; // should dereferencing be implicit here as well?

我认为这会比有两个分开的运算符更加混乱。

同时,拥有两个运算符可以帮助您跟踪您有多少层间接引用。尽管 -> 运算符在这方面并不是必需的,因为 p->x 等效于 (*p).x,但它确实使代码更清晰、更易读。


你还需要考虑当涉及到额外的间接层级时应该发生什么:当使用“.”时,您是否希望允许编译器取消引用任意深度的结构指针,还是将其限制在最多一级间接层级?对我来说,两种解决方案都不太“正确”... - Christoph
嗯,由于在某些语言中(只有 . 用于 ->::),这是可行的。而且似乎从那些语言转到 C 或 C++ 的人会觉得区分它们很困惑。 - sbi
请参考此答案 - sbi
1
@sbi: 是的。然而,在大多数其他语言中,你实际上不必像我们在C和C++中所面临的那样处理多个间接级别(可能有例外,但我想到的语言没有)。 - James McNellis
1
当然,这是正确的,这些语言在其他方面也往往模糊了引用和被引用对象之间的区别。我只是指出C和C++处理这个问题的方式并不是“唯一真正正确的方式”,而且它似乎自然而然地只对我们有意义,因为我们已经这样做了很长时间。 - sbi

2
是的,歧义来自于能够重载两个运算符。最好的例子可能是共享指针。共享指针可以与 . 和 -> 运算符一起使用,而两者具有不同的含义。
使用 -> 可以访问所指向的对象,而使用 . 可以访问共享指针本身的成员。
例如:
class MyObject {
 public:
    void myFunction() {}
 };
 boost::shared_ptr<MyObject> ptr;
 ptr.use_count(); // calls use_count, which is a member of boost::shared_ptr.
 ptr->myFunction(); // calls MyObject::myFunction, as the operator-> is overriden

0

当你拥有一种本质上旨在成为“可移植汇编器”的语言时,你不会试图向用户隐藏实现细节。当然,编译器可以确定在表达式a.b中所涉及的a是一个指针。你能吗?可靠地?在复杂混乱的代码中始终如一?而且你难道不能想象出一种情况,在这种情况下,无法快速注意到a是一个指针可能会成为一个问题吗?

停止以“难以编写”为思考方式,开始以“易于阅读”为思考方式。(是的,我知道。这与整个C程序员神话背道而驰!)你将比编写代码多几个数量级地阅读代码。


0

C++ 允许您重载 -> 运算符。当您有一个智能指针类,例如 std::auto_ptr 时,同一变量可能同时支持 .->,您可以使用 . 访问 auto_ptr 的成员,使用 -> 访问其包含的指针的成员。


-1

(*a).ba->b 是一样的。


-1

无论是fo->bar还是(*fo).bar都是相同的操作!

语言只是提供了一个间接访问运算符,即箭头(->),并将其视为单个符号。


为什么这个被点赞了?它并没有回答问题。 - Good Person
@Good,实际上,您编辑了您的问题! - Secko

-1

-> 运算符只是通过指针引用对象的方法或成员变量更加简便的方法,而不必使用 (*p).member 或 (*p).method 这样的方式。

例如:

MyClass *MyObj;

MyObj->method(); 比 (*MyObj).method(); 更容易阅读和理解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接