C++学习笔记-箭头运算符

箭头运算符(->)是指针访问成员的语法糖,它等价于先解引用再访问成员。通过重载箭头运算符,我们可以让自定义类型表现得像指针一样,这在实现智能指针和迭代器时非常有用。

箭头运算符的基本概念

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

class Entity
{
public:
    void Print() const { std::cout << "Hello!" << std::endl; }
    int value = 42;
};

int main()
{
    Entity e;
    e.Print();  // 直接访问成员

    Entity* ptr = &e;
    ptr->Print();  // 箭头运算符访问成员
    (*ptr).Print();  // 等价写法:先解引用再访问成员
    
    std::cout << "ptr->value = " << ptr->value << std::endl;
    std::cout << "(*ptr).value = " << (*ptr).value << std::endl;
}

重载箭头运算符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class SmartPtr
{
private:
    Entity* m_Entity;
public:
    SmartPtr(Entity* entity) : m_Entity(entity) {}
    ~SmartPtr() { delete m_Entity; }

    // 传统方式:需要调用GetObject()
    const Entity* GetObject() const { return m_Entity; }

    // 重载箭头运算符
    const Entity* operator->() const { return m_Entity; }
    
    // 非const版本
    Entity* operator->() { return m_Entity; }
};

int main()
{
    {
        SmartPtr sptr(new Entity());
        
        // 传统方式:不够优雅
        sptr.GetObject()->Print();
        
        // 使用重载的箭头运算符:更优雅
        sptr->Print();
        sptr->value = 100;
        std::cout << "Value: " << sptr->value << std::endl;
    }  // SmartPtr析构,自动删除Entity
}

实现一个完整的智能指针

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
template<typename T>
class UniquePtr
{
private:
    T* m_Ptr;
    
public:
    explicit UniquePtr(T* ptr) : m_Ptr(ptr) {}
    
    ~UniquePtr()
    {
        delete m_Ptr;
    }
    
    // 禁用拷贝
    UniquePtr(const UniquePtr&) = delete;
    UniquePtr& operator=(const UniquePtr&) = delete;
    
    // 移动构造函数
    UniquePtr(UniquePtr&& other) noexcept : m_Ptr(other.m_Ptr)
    {
        other.m_Ptr = nullptr;
    }
    
    // 移动赋值运算符
    UniquePtr& operator=(UniquePtr&& other) noexcept
    {
        if (this != &other)
        {
            delete m_Ptr;
            m_Ptr = other.m_Ptr;
            other.m_Ptr = nullptr;
        }
        return *this;
    }
    
    // 箭头运算符
    T* operator->() const
    {
        return m_Ptr;
    }
    
    // 解引用运算符
    T& operator*() const
    {
        return *m_Ptr;
    }
    
    // 转换为bool
    explicit operator bool() const
    {
        return m_Ptr != nullptr;
    }
    
    // 获取原始指针
    T* Get() const { return m_Ptr; }
    
    // 释放所有权
    T* Release()
    {
        T* temp = m_Ptr;
        m_Ptr = nullptr;
        return temp;
    }
    
    // 重置指针
    void Reset(T* ptr = nullptr)
    {
        delete m_Ptr;
        m_Ptr = ptr;
    }
};

class TestClass
{
private:
    std::string m_Name;
    int m_Value;
    
public:
    TestClass(const std::string& name, int value) 
        : m_Name(name), m_Value(value)
    {
        std::cout << "Create " << m_Name << std::endl;
    }
    
    ~TestClass()
    {
        std::cout << "Destroy " << m_Name << std::endl;
    }
    
    void DoSomething() const
    {
        std::cout << m_Name << " is doing something (value: " << m_Value << ")" << std::endl;
    }
    
    void SetValue(int value) { m_Value = value; }
    int GetValue() const { return m_Value; }
    const std::string& GetName() const { return m_Name; }
};

int main()
{
    {
        UniquePtr<TestClass> ptr(new TestClass("MyObject", 42));
        
        if (ptr)  // 使用operator bool
        {
            ptr->DoSomething();      // 使用operator->
            ptr->SetValue(100);      // 使用operator->
            
            (*ptr).DoSomething();    // 使用operator*
            
            std::cout << "Value: " << ptr->GetValue() << std::endl;
        }
    }  // ptr离开作用域,TestClass自动销毁
    
    std::cout << "UniquePtr destroyed" << std::endl;
}

箭头运算符的链式调用

箭头运算符可以链式调用,编译器会递归地应用箭头运算符:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Wrapper
{
private:
    UniquePtr<TestClass> m_Ptr;
    
public:
    Wrapper(TestClass* obj) : m_Ptr(obj) {}
    
    // 返回UniquePtr的引用
    UniquePtr<TestClass>& operator->()
    {
        return m_Ptr;
    }
    
    const UniquePtr<TestClass>& operator->() const
    {
        return m_Ptr;
    }
};

int main()
{
    Wrapper wrapper(new TestClass("Wrapped", 123));
    
    // 链式箭头运算符调用:
    // wrapper-> 返回 UniquePtr<TestClass>&
    // UniquePtr<TestClass>& -> 返回 TestClass*
    // TestClass* -> 访问成员
    wrapper->DoSomething();
    wrapper->SetValue(456);
    
    std::cout << "Final value: " << wrapper->GetValue() << std::endl;
}

实现迭代器的箭头运算符

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
template<typename T>
class SimpleVector
{
private:
    T* m_Data;
    size_t m_Size;
    size_t m_Capacity;
    
public:
    SimpleVector() : m_Data(nullptr), m_Size(0), m_Capacity(0) {}
    
    ~SimpleVector()
    {
        delete[] m_Data;
    }
    
    void PushBack(const T& item)
    {
        if (m_Size >= m_Capacity)
        {
            m_Capacity = m_Capacity == 0 ? 1 : m_Capacity * 2;
            T* newData = new T[m_Capacity];
            for (size_t i = 0; i < m_Size; ++i)
                newData[i] = m_Data[i];
            delete[] m_Data;
            m_Data = newData;
        }
        m_Data[m_Size++] = item;
    }
    
    // 简单的迭代器实现
    class Iterator
    {
    private:
        T* m_Ptr;
        
    public:
        Iterator(T* ptr) : m_Ptr(ptr) {}
        
        // 箭头运算符
        T* operator->() const
        {
            return m_Ptr;
        }
        
        // 解引用运算符
        T& operator*() const
        {
            return *m_Ptr;
        }
        
        // 前置递增
        Iterator& operator++()
        {
            ++m_Ptr;
            return *this;
        }
        
        // 比较运算符
        bool operator!=(const Iterator& other) const
        {
            return m_Ptr != other.m_Ptr;
        }
    };
    
    Iterator begin() { return Iterator(m_Data); }
    Iterator end() { return Iterator(m_Data + m_Size); }
};

class Person
{
private:
    std::string m_Name;
    int m_Age;
    
public:
    Person(const std::string& name, int age) : m_Name(name), m_Age(age) {}
    
    void Introduce() const
    {
        std::cout << "Hi, I'm " << m_Name << ", " << m_Age << " years old." << std::endl;
    }
    
    const std::string& GetName() const { return m_Name; }
    int GetAge() const { return m_Age; }
};

int main()
{
    SimpleVector<Person> people;
    people.PushBack(Person("Alice", 25));
    people.PushBack(Person("Bob", 30));
    people.PushBack(Person("Charlie", 35));
    
    std::cout << "Using iterator with arrow operator:" << std::endl;
    for (auto it = people.begin(); it != people.end(); ++it)
    {
        it->Introduce();  // 使用迭代器的箭头运算符
        std::cout << "Age: " << it->GetAge() << std::endl;
    }
}

箭头运算符的特殊性质

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class ArrowTest
{
private:
    int m_Value;
    
public:
    ArrowTest(int value) : m_Value(value) {}
    
    void Print() const
    {
        std::cout << "Value: " << m_Value << std::endl;
    }
    
    int GetValue() const { return m_Value; }
};

class ArrowProxy
{
private:
    ArrowTest* m_Target;
    
public:
    ArrowProxy(ArrowTest* target) : m_Target(target) {}
    
    // 箭头运算符必须返回指针或者重载了箭头运算符的对象
    ArrowTest* operator->() const
    {
        std::cout << "ArrowProxy::operator-> called" << std::endl;
        return m_Target;
    }
};

class ArrowChain
{
private:
    ArrowProxy m_Proxy;
    
public:
    ArrowChain(ArrowTest* target) : m_Proxy(target) {}
    
    // 返回重载了箭头运算符的对象
    ArrowProxy operator->() const
    {
        std::cout << "ArrowChain::operator-> called" << std::endl;
        return m_Proxy;
    }
};

int main()
{
    ArrowTest test(42);
    ArrowProxy proxy(&test);
    ArrowChain chain(&test);
    
    std::cout << "=== Direct access ===" << std::endl;
    test.Print();
    
    std::cout << "\n=== Through proxy ===" << std::endl;
    proxy->Print();
    
    std::cout << "\n=== Through chain ===" << std::endl;
    chain->Print();  // 会依次调用ArrowChain::operator->和ArrowProxy::operator->
}

实际应用:观察者模式

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
class Subject;

class Observer
{
public:
    virtual void Update(const Subject* subject) = 0;
    virtual ~Observer() = default;
};

class Subject
{
private:
    std::vector<Observer*> m_Observers;
    int m_State;
    
public:
    Subject(int state) : m_State(state) {}
    
    void Attach(Observer* observer)
    {
        m_Observers.push_back(observer);
    }
    
    void SetState(int state)
    {
        m_State = state;
        NotifyAll();
    }
    
    int GetState() const { return m_State; }
    
private:
    void NotifyAll()
    {
        for (Observer* observer : m_Observers)
        {
            observer->Update(this);
        }
    }
};

// 智能观察者指针
class ObserverPtr
{
private:
    Observer* m_Observer;
    Subject* m_Subject;
    
public:
    ObserverPtr(Observer* observer, Subject* subject) 
        : m_Observer(observer), m_Subject(subject)
    {
        if (m_Subject)
            m_Subject->Attach(m_Observer);
    }
    
    Observer* operator->() const
    {
        return m_Observer;
    }
    
    Observer& operator*() const
    {
        return *m_Observer;
    }
};

class ConcreteObserver : public Observer
{
private:
    std::string m_Name;
    
public:
    ConcreteObserver(const std::string& name) : m_Name(name) {}
    
    void Update(const Subject* subject) override
    {
        std::cout << m_Name << " received update: state = " 
                  << subject->GetState() << std::endl;
    }
    
    void DoSomething()
    {
        std::cout << m_Name << " is doing something" << std::endl;
    }
};

int main()
{
    Subject subject(0);
    
    ObserverPtr obs1(new ConcreteObserver("Observer1"), &subject);
    ObserverPtr obs2(new ConcreteObserver("Observer2"), &subject);
    
    obs1->DoSomething();  // 使用箭头运算符
    obs2->DoSomething();
    
    subject.SetState(10);
    subject.SetState(20);
}

总结

  1. 箭头运算符本质:指针访问成员的语法糖,等价于先解引用再访问成员
  2. 重载用途:让自定义类型表现得像指针一样,常用于智能指针和迭代器
  3. 返回类型:必须返回指针或者重载了箭头运算符的对象
  4. 链式调用:编译器会递归地应用箭头运算符,直到得到真正的指针
  5. 实际应用:智能指针、迭代器、代理模式等场景中广泛使用
updatedupdated2025-09-202025-09-20