当前位置: 首页 > news >正文

C++中的友元 之八

一、我们先搞清楚一个目标

C++ 标准库追求一个核心原则:

像用普通指针一样高效
但比指针更安全、更抽象

这就是所谓的:

零成本抽象(Zero-cost abstraction)

提出这个理念的人是
Bjarne Stroustrup

意思是:

你获得抽象能力
但运行时不付出额外成本


二、先看最简单的情况:指针

假设你有数组:

int arr[3] = {1,2,3};

遍历:

for(int* p = arr; p != arr + 3; ++p)
{std::cout << *p;
}

这里:

  • p 本质是地址
  • ++p 是地址 + sizeof(int)
  • *p 是解引用

这是最原始、最高效的方式。


三、现在换成 vector

std::vector<int> v = {1,2,3};for(auto it = v.begin(); it != v.end(); ++it)
{std::cout << *it;
}

问题来了:

这个 it 是什么?

答案:

它是一个 iterator 对象
本质上封装了一个指针


四、我们自己写一个极简 vector + iterator

我们做一个简化版理解。

class MyVector
{
public:MyVector(int* data) : data_(data) {}class Iterator{public:Iterator(int* ptr) : ptr_(ptr) {}int& operator*() { return *ptr_; }Iterator& operator++(){++ptr_;return *this;}bool operator!=(const Iterator& other) const{return ptr_ != other.ptr_;}private:int* ptr_;};Iterator begin() { return Iterator(data_); }Iterator end()   { return Iterator(data_ + 3); }private:int* data_;
};

注意:

Iterator 只是:

int* ptr_;

它内部就一个指针。


五、零成本在哪里?

看这句:

int& operator*() { return *ptr_; }

编译后:

  • 和直接 *ptr 一样
  • 不会多出开销
  • 会被 inline

所以:

*it

等价于:

*pointer

这就是零成本。


六、那 friend 在哪?

现在进入关键部分。

在真实标准库里:

iterator 往往需要访问容器内部结构。

比如 vector 里:

  • 内部有 T* data_
  • size_
  • capacity_

iterator 需要:

  • 访问 data_
  • 计算偏移
  • 做边界判断(调试模式)

但:

这些成员是 private

怎么办?


七、标准库常见写法(简化示意)

class Vector
{
private:int* data_;size_t size_;public:class Iterator{int* ptr_;public:int& operator*() { return *ptr_; }private:friend class Vector;Iterator(int* p) : ptr_(p) {}};Iterator begin(){return Iterator(data_);}
};

这里发生了什么?

  1. Iterator 构造函数是 private
  2. 只有 Vector 能创建 Iterator
  3. 外部不能乱造

这是第一层 friend 用法。


八、更关键的 friend 场景

很多标准库实现是这样结构:

  • 容器类
  • 迭代器类
  • 算法函数

它们彼此需要访问 private。

例如:

class Vector
{friend class VectorIterator;
};

这样:

  • Iterator 可以直接访问 data_
  • 不需要 getter
  • 不需要 public 暴露内部

保持封装 + 保持性能。


九、为什么不用 getter?

你可能会问:

“为什么不写 getData()?”

因为:

  1. 暴露内部结构
  2. 增加接口污染
  3. 破坏抽象
  4. 有时影响优化

friend 只对特定类开放权限。

这是:

精准授权


十、零成本抽象的关键组合

标准库 iterator 成功的关键是:

  1. 小对象(通常只一个指针)
  2. 全部 inline
  3. 模板
  4. friend 精准授权

组合起来效果是:

语法像对象
性能像指针


十一、真正震撼的一点

当你写:

std::sort(v.begin(), v.end());

sort 不知道 vector 的内部结构。

它只通过 iterator 操作。

iterator 又只是指针包装。

最终生成的汇编代码:

和直接排序数组几乎一样。

这就是 C++ 的魔法。


十二、friend 在其中的作用总结

friend 让:

  • iterator 可以访问容器内部
  • 容器可以构造 iterator
  • 不暴露实现细节
  • 不增加运行时成本

它建立了一个:

内部信任域

但对外保持封装。


十三、为什么这对你重要?

你做高性能数据采集。

想象你写:

class FrameBuffer
{float* data_;
};

你可以写:

class FrameIterator
{float* ptr_;
};

用 friend 连接它们。

结果:

  • 抽象干净
  • 性能等于裸指针
  • 代码可维护

这就是标准库给你的启示。


十四、现在你真正应该理解的核心

iterator 不是“复杂对象”。

它通常只是:

一个指针 + 一些 inline 操作

friend 让:

它能访问容器内部
但不污染容器接口

这才是零成本抽象的精髓。


十五、最后一句话

C++ 的 iterator 设计哲学是:

用类模拟指针
用 friend 保证封装
用 inline 保证性能

这三者组合起来,才是现代 C++ 的威力。


http://www.jsqmd.com/news/415537/

相关文章:

  • 2026Q1石家庄别墅装修综合排名TOP10(绿色智能版靠谱实测推荐) - 品牌智鉴榜
  • greenplum安装部署-CentOS7.9
  • P1880 [NOI1995] 石子合并
  • 搭建一套.net下能落地的飞书考勤系统
  • LDSC安装
  • 有趣的代码-值传递和引用传递
  • 洛谷 B2161:十进制转二进制 ← 字符串 / 栈
  • Educational Codeforces Round 187 解题报告
  • openclaw安装对接配置
  • 洛谷P3375 【模板】KMP字符串匹配
  • B002 排序 双指针 哈希表 两数之和到K数之和 1640~1642 CSES
  • 110kV三段式相间距离保护参数整定计算设计simulink仿真
  • 【每日一题】LeetCode 1404. 将二进制表示减到 1 的步骤数
  • 【村儿网通】把 Scaled Dot-Product Attention 展开写一遍
  • Andrew Stankevich Contest 44 (ASC 44) 总结
  • nohup ./webserver
  • 基于Lyapunov的控制器设计用于自主水下车辆(AUV)的轨迹跟踪,对于欠驱动的自主水下车辆(AUV)进行二维轨迹跟踪的仿真Lyapunov控制器设计附Simulink仿真、Matlab代码
  • 基于LSTM和SVM的设备故障诊断附Matlab代码
  • C++中的友元 之七
  • CT断层成像系列10——三维锥束FDK重建算法(附Matlab代码)
  • 东方博宜OJ 1108:正整数N转换成一个二进制数 ← 字符串 / 栈
  • 渗透测试零基础入门!从环境搭建到实战靶场通关,一篇吃透
  • 【渗透测试】一文吃透SQL注入漏洞!原理+分类+实战利用+防御方案
  • 260204
  • 【Playwright 】端到端自动化的开源框架
  • 【matlab】GUI句柄
  • 专业的文件上传漏洞检测工具,支持263+绕过技术、代理抓包、动态扫描
  • C++中的友元 之六
  • 五款免费AI视频生成神器,效果炸裂!
  • STM32F103C8T6 驱动 180° 舵机(SG90)超详细教程