C++怎么重载中括号 C++ subscript operator[]重载示例【重载】

7次阅读

operator[]必须是非静态成员函数,因需访问对象内部状态;应返回引用以支持赋值,并提供const版本;越界检查非强制但推荐用at()实现;多维访问需proxy对象,注意生命周期与校验分工。

C++怎么重载中括号 C++ subscript operator[]重载示例【重载】

operator[] 必须是非静态成员函数

因为 operator[] 需要访问对象的内部状态(比如数组指针、大小等),它只能作为类的非静态成员函数实现,不能是全局函数或静态成员。写成全局函数会编译报错:Error: 'operator[]' must be a non-Static member function

常见错误是想“对称地”像 operator+ 那样写成友元或全局,但 c++ 语法强制要求它绑定到实例——毕竟 a[i] 的语义天然依赖于 a 的状态。

  • 必须声明为 T& operator[](size_t i)const T& operator[](size_t i) const
  • 返回引用(T&)才能支持赋值,如 v[0] = 42
  • 通常需配套提供 const 版本,否则 const MyVec v; v[0] 会编译失败

下标越界不自动抛异常,得自己检查

C++ 标准库(如 std::vector::operator[])不检查越界,这是性能考量;你自己重载时也默认不检查——如果忘了加判断,就容易读写非法内存,引发未定义行为(崩溃、数据错乱、静默损坏)。

要不要检查,取决于使用场景:

立即学习C++免费学习笔记(深入)”;

  • 追求极致性能且调用方可信(如内部算法库)→ 不检查,靠断言 assert(i
  • 面向外部用户或调试阶段 → 显式抛异常:if (i >= size_) throw std::out_of_range("index " + std::to_string(i));
  • 注意:不要在 const 版本里用 assert 后直接 return,否则非 const 版本可能绕过检查

返回 proxy 对象才能支持 v[i][j] 多维语法

如果类表示二维容器(如矩阵),想让 mat[i][j] 工作,不能让 operator[] 直接返回 int*std::vector&——那样会暴露内部结构,且无法控制第二维访问逻辑。

正确做法是返回一个代理(proxy)对象,它自己也重载 operator[]

class Matrix {     std::vector> data_; public:     class RowProxy {         std::vector& row_;     public:         RowProxy(std::vector& r) : row_(r) {}         int& operator[](size_t j) { return row_[j]; }         const int& operator[](size_t j) const { return row_[j]; }     };     RowProxy operator[](size_t i) { return RowProxy(data_[i]); }     const RowProxy operator[](size_t i) const { return RowProxy(data_[i]); } };

proxy 对象生命周期需谨慎:它持的是引用,不能返回局部 vector 的引用;若底层存储可能 realloc(如 push_back),proxy 可能悬空。

operator[] 和 at() 的分工要明确

标准实践是:让 operator[] 走快速路径(无检查或仅 debug 断言),把带边界检查的版本留给 at() 成员函数——这和 std::vector 保持一致,使用者一看就懂语义差异。

  • v[i] → 假设调用方已校验,快;v.at(i) → 安全,抛异常
  • 别在 operator[] 里做 at() 的事,否则失去性能优势
  • 如果类本身不维护 size(比如包装 C 数组),at() 就更需要显式传入长度参数,避免误用

多维容器中 proxy 的 operator[] 也应遵循同样原则:只做索引转发,不重复校验;真正检查放在 at() 或 proxy 的构造里。

text=ZqhQzanResources