为什么C ++中的箭头运算符不只是*。的别名?


18

在c ++中,*运算符可以重载,例如使用迭代器,但是箭头(->)(。*)运算符不适用于重载*运算符的类。我认为预处理器可以轻松地用(* left).right替换->的所有实例,这将使迭代器更易于实现。->与众不同是不是有实际的原因,还是仅是语言/设计者的特殊性?

Answers:


16

foo->bar相等的规则(*foo).bar仅适用于内置运算符。

一元operator *并不总是具有指针取消引用语义。我可以建立一个库,在其中表示矩阵转置,零个或多个解析器匹配或几乎所有其他内容。

如果重载一元数的任何内容operator *突然获得了operator ->您不要求的语义,这可能会使语言更加麻烦。

operator -> 是可单独重载的,因此,如果您想要一个,可以以最小的努力重载一个。

还要注意,这种重载将具有一些非常有趣的属性,例如自动链接operator ->调用,直到链接中的一个返回原始指针为止。这对于智能指针和其他代理类型非常有用。

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <iostream>
#include <ostream>

struct Foo
{
    boost::shared_ptr<std::string> operator -> () const
    {
        return boost::make_shared<std::string>("trololo");
    }
};

int main()
{
    Foo foo;
    std::cerr << foo->size() << std::endl;
}

您的示例说明了什么?您是否正在返回指向字符串的智能指针并以某种方式输出大小?我很困惑。
Trevor Hickey 2012年

2
它说明了我的答案的最后一段,即如何使用->运算符链,直到它获得指向某事物的原始指针,取消引用和访问它的成员。如果操作符->未链接,则该示例格式不正确,因为shared_ptr不是原始指针。
拉尔斯·维克伦德

@LarsViklund:您的答案有一个问题:您说“ operator-> ...自动链接operator->调用,直到该链接中的一个返回原始指针为止”。这是不正确的- A->B最多使用1个附加调用的语法链。C ++->二进制语法的实际作用不是opeartor->直接调用对象的-而是查看对象的类型A并检查其原始指针。如果是,则->对它进行解引用并B在其上执行,否则它将调用该对象的operator->,对结果进行解引用(使用本机原始指针或另一个operator->,然后B对该结果执行
Guss

@Guss:我找不到您要求的任何章节,也无法在编译器中复制它。C ++ 11 13.5.6 / 1指示如果存在适当的重载,x->m应将其解释为(x.operator->())->m。如果LHS operator->再次具有适当的过载,则此过程将重复进行,直到只有(*x).m5.2.5 / 2 的通常效果为止。
Lars Viklund 2014年

8

“ C ++编程语言”描述了以下事实:这些运算符是不同的,因此它们可以是不同的,但还表示:

如果提供不止这些运营商之一,它可能是明智的,提供等价,只是因为它是明智的,以确保++xx+=1具有相同的效果x=x+1进行一个简单的变量x的一些类如++,+ =,=,和提供了+。

因此,似乎语言设计者提供了单独的重载点,因为您可能希望以不同的方式重载它们,而不是假设您始终希望它们是相同的。


7

通常,C ++旨在提高灵活性,因此*和的重载->是分开的。尽管这样做是非常不寻常的,但是如果您想做的足够糟糕,则可以编写这些重载来完成完全不同的事情(例如,对于在C ++中实现的特定于域的语言可能有意义)。

也就是说,迭代器确实支持这两种用法。在古老的实现中,您可能会找到需要(*iter).whatever而不是的库iter->whatever,但是如果是这样,那是实现中的错误,而不是语言的特征。考虑到实现所有标准容器/算法/迭代器所需的工作量,某些早期发行版虽然有些不完整也就不足为奇了,但从未真正打算如此。


我没有意识到标准库容器已实现->,或者它是可重载的。
雅各布·韦斯布拉特

3
C ++ 03 24.1 / 1要求任何(*i).m有效的迭代器都必须支持i->m相同的语义。
拉尔斯·维克伦德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.