C++之Pointer-Like Classes

本文详细介绍了C++中的智能指针和迭代器的概念及应用。以shared_ptr为例,展示了如何通过智能指针对传统指针进行封装以增强功能和安全性。同时,通过链表迭代器的具体实现说明了迭代器作为一种特殊的指针类,在容器遍历中的作用。

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

    C++中构造的类一般会像两种东西,像指针(称为pointer-like classes,指针类),或者像函数(称为function-like classes,函数类)。一个类被设计成指针,被当作指针来使用,是因为我们想在传统指针的基础上多实现功能,或者说想对指针有更多的控制。常见的指针类有两种:智能指针和迭代器。

    关于智能指针

    C++中常见的智能指针有auto_ptr,scoped_ptr,shared_ptr等等。下面来介绍shared_ptr,智能指针内部一定有一个真正的指针,图示为:


其中,大圆圈表示一个智能指针,里面包含一个真正的指针px,指向实际所指的对象。

     对于智能指针,和传统的指针一样,会使用两种操作符,*解引用(dereference)操作符和->成员访问操作符。在智能指针类中要提供这两种操作符重载operator* ( )和operator-> ( )

template<class T>
class shared_ptr
{
public:
  T& operator*() const
  { return *px; }
  T* operator->() const
  { return px; }

  shared_ptr(T* p) : px(p) {}
private:
  T* p;
  long* pn;
...
};

    在智能指针shared_ptr内有一个真正的指针px,指向对象T。下面的代码示范了智能指针的用法:

struct Foo
{
  ...
  void method(void) {...}
};
shared_ptr<Foo> sp(new Foo);//定义了一个指向Foo类型的智能指针
Foo f(*sp);//定义了一个Foo对象,并使用智能指针sp所指的对象来初始化
sp->method();//相当于px->method();

    现在有一个类Foo,第1行产生了一个天然的指针sp,通过调用智能指针的构造函数,我们把天然的指针包装在智能指针内。第2行当我们解引用*sp,就相当于return *px。第3行sp->method();的意思是想通过智能指针sp调用成员函数method,首先会调用操作符重载operator->( ) const,得到智能指针内部真正的指针px,然后再通过px调用函数method(px->method();)。在C++中规定,对于调用->操作符之后,->操作符并不会消耗掉,而是继续作用下去。

    关于迭代器

    迭代器指向容器中的元素,可以被看做智能指针。不过迭代器除了要提供*和->操作外,还要提供++,--(用于指针移动,可以遍历容器),==和!=操作。下面的代码以链表的迭代器为例:

template<class T>
struct __list_node
{
  void* prev;
  void* next;
  T data;
};
template<class T, class Ref, class Ptr>
struct __list_iterator
{
  typedef __list_iterator<T, Ref, Ptr> self;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef __list_node<T>* link_type;
  link_type node;
  bool operator== (const self& x) const { return node == x.node; }
  bool operator!= (const self& x) const { return node != x.node; }
  reference operator*() const { return (*node).data; }
  pointer operator->() const { return &(operator*()); }
  self& operator++() { node = (link_type)((*node).next); return *this; }
  self operator++(int) {self tmp = *this; ++*this; return tmp; }
  self& operator--() { node = (link_type)((*node).prev); return *this; }
  self operator--(int) {self tmp = *this; --*this; return tmp; }
};

    链表的数据结构如图所示:


    链表的节点包含三个部分,分别是前一个节点的指针prev,后一个节点的指针next,和数据data。图示中的“大泡泡”表示迭代器_list_iterator,其中包含一个真实的指针node,用来指向链表中的节点。从程序中可以看到,_list_iterator除了提供*和->操作,还提供了++,--操作。对迭代器进行++操作,会指向下一个元素,对迭代器进行--操作,会指向前一个元素。由于node只是指向整个节点,为了取得节点的数据,还需要调用(*node).data

    _list_iterator的使用示例代码如下:

struct Foo
{
  void method()
  { cout << "method" << endl; }
};

ll::_list_iterator<Foo, Foo&, Foo*> iter;
*iter; //获得一个Foo对象
iter->method(); //意思是调用Foo::method(),相当于(*iter).method,也相当于(&(*iter))->method()
    首先,我们声明一个_list_iterator迭代器iter。我们知道迭代器也是一种指针类,可以模拟指针的操作。通过*操作符,我们可以得到一个Foo对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值