operator*() 和 operator->()

本文探讨了《STL源码剖析》中迭代器的实现原理,特别是operator*和operator->的重载方式。通过对比不同实现,解释了为何选择通过operator*间接获取指针的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在看侯捷的《STL源码剖析》,在实现iterator的时候,肯定要重载*和->。比如__deque_iterator里面的这两个操作符重载如下:

reference operator*() const { return *cur; }

pointer operator->() const { return &(operator*()); }

我一直觉得STL的源码很美,但这里我却有个疑问。为什么operator->()要这样实现,而不是简单的return cur;

我在VC8自带的头文件里面看到了这样的实现:

reference operator*() const
{    // return designated object
    size_type _Block = _Myoff / _DEQUESIZ;
    size_type _Off = _Myoff & (_DEQUESIZ - 1);    // assume power of 2
    _SCL_SECURE_VALIDATE(this->_Mycont != NULL);
    _SCL_SECURE_VALIDATE_RANGE(_Myoff < ((_Mydeque *)(this->_Mycont))->_Myoff + ((_Mydeque *)(this->_Mycont))->_Mysize);
    if (this->_Mycont->_Mapsize <= _Block)
        _Block -= this->_Mycont->_Mapsize;
    return ((this->_Mycont->_Map)[_Block][_Off]);
}

pointer operator->() const
{    // return pointer to class object
    return (&**this);
}

先不用去研究operator*()的具体实现,但是可以看到operator->()的实现也很独特,其实就是在(*this)上调用operator*(),再对其返回值取地址。

我想这样做也有原因,大概是为了统一吧。一般说来在operator->()中调用operator*()再取地址,应该没有什么错,我们不必在operator->()再去访问其底层实现。比如在VC8的版本中,operator*()的实现不是非常的直观简单,也许operator->()要访问其底层实现也会这么复杂,又不统一,又容易出错。

由此STL这样的代码就是很合理了。

<think>好的,我现在需要回答用户的问题:为什么运算符 -> 或 ->* 可以应用于 struct Book 类型而不是指针类型,以及它们在C++中的应用原理。首先,我得回忆一下C++中结构体运算符的相关知识。 用户提到的->->*运算符,通常用于指针访问对象的成员。比如,如果有一个指向结构体的指针ptr,那么ptr->member就是访问该指针所指向的结构体的成员。但用户的问题是,为什么这些运算符可以用于结构体类型本身,而不是指针类型。这似乎常规用法相反,可能需要进一步分析。 根据引用[5],C++中的structclass非常相似,成员默认是public的。可能结构体对象本身可以重载运算符?比如,如果结构体Book重载了operator->,那么当使用对象实例时,->操作符就会调用该重载的方法。这可能是一个方向。 另外,->*运算符用于指向成员的指针,比如有一个成员变量指针,可以通过对象指针->*来访问。但如果是结构体对象本身,可能需要看是否有相关的运算符重载。 我需要确认C++中运算符重载的规则。例如,operator->在重载时,必须返回一个指针类型,或者另一个重载了operator->的对象,这样编译器会递归调用直到得到一个指针。例如,智能指针通常重载operator->来提供类似指针的行为。 假设用户定义了一个struct Book,并且该结构体重载了operator->,那么当使用Book对象时,obj->member实际上会调用obj.operator->(),然后获取一个指针,再访问member。这种情况下,即使obj不是指针,也能使用->运算符。 同样,->*运算符可以重载,用于处理成员指针。例如,如果有一个指向Book成员的指针,可以通过对象->*来访问,但需要结构体支持这样的操作符重载。 不过,常规情况下,->是用于指针的,如果结构体没有重载这些运算符,直接对对象使用会导致编译错误。因此,用户的问题可能是在特定情况下,比如结构体内部有运算符重载,或者用户误解了某些代码。 需要检查用户提供的引用内容。在引用[2]中,提到了结构指针的例子,(*him).first等价于him->first,这说明->用于指针访问成员。引用[5]提到struct可以包含成员函数,所以可能用户遇到的结构体Book有重载operator->的情况。 总结:当结构体Book重载了operator->或operator->*时,即使对象不是指针,也可以使用这些运算符。运算符重载使得对象表现得像指针一样,编译器会自动调用相应的重载方法。</think>在C++中,运算符`->``->*`通常用于指针类型访问成员或成员指针,但在某些情况下也可直接应用于`struct Book`类型的对象。其核心原理是**运算符重载****成员指针的访问规则**。以下是具体分析: --- ### 1. **运算符 `->` 的应用原理** - **常规用法**:`->`用于指针类型访问成员,例如: ```cpp struct Book { int pages; }; Book* ptr = new Book; ptr->pages = 100; // 通过指针访问成员 ``` - **应用于非指针类型**: 若`struct Book`重载了`operator->`,则对象可直接使用`->`: ```cpp struct Book { int pages; Book* operator->() { return this; // 返回指针,使对象支持->操作 } }; Book book; book->pages = 100; // 实际调用book.operator->()->pages ``` 编译器会将`book->pages`解析为`book.operator->()->pages`,最终通过返回的指针访问成员[^5]。 --- ### 2. **运算符 `->*` 的应用原理** - **常规用法**:`->*`用于指针类型结合成员指针访问数据: ```cpp struct Book { int pages; }; int Book::*ptr = &Book::pages; // 定义成员指针 Book* obj = new Book; obj->*ptr = 100; // 通过指针成员指针赋值 ``` - **应用于非指针类型**: 若`struct Book`重载了`operator->*`,则对象可直接使用`->*`: ```cpp struct Book { int pages; int operator->*(int Book::*mp) { return this->*mp; // 返回成员指针指向的值 } }; Book book; int Book::*ptr = &Book::pages; book->*ptr = 100; // 实际调用book.operator->*(ptr) ``` 需注意,`->*`的重载需严格匹配成员指针类型。 --- ### 3. **关键区别:运算符重载 vs 默认行为** - **指针类型**:`->``->*`的默认行为是直接访问指针指向的成员。 - **非指针类型**:需通过重载运算符实现类似功能,本质上是对对象行为的扩展[^5]。 --- ### 代码示例 ```cpp #include <iostream> struct Book { int pages; // 重载 operator-> Book* operator->() { return this; } // 重载 operator->* int& operator->*(int Book::*mp) { return this->*mp; } }; int main() { Book book; book->pages = 200; // 调用 operator->() std::cout << book.pages << std::endl; // 输出 200 int Book::*ptr = &Book::pages; book->*ptr = 300; // 调用 operator->*() std::cout << book.pages << std::endl; // 输出 300 return 0; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值