operator[]必须是非静态成员函数,因需访问对象内部状态;应返回引用以支持赋值,并提供const版本;越界检查非强制但推荐用at()实现;多维访问需proxy对象,注意生命周期与校验分工。
因为 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 MyVec v; v[0] 会编译失败C++ 标准库(如 std::vector::operator[])不检查越界,这是性能考量;你自己重载时也默认不检查——如果忘了加判断,就容易读写非法内存,引发未定义行为(崩溃、数据错乱、静默损坏)。
要不要检查,取决于使用场景:
assert(i
if (i >= size_) throw std::out_of_range("index " + std::to_string(i));
const 版本里用 assert 后直接 return,否则非 const 版本可能绕过检查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[] 走快速路径(无检查或仅 debug 断言),把带边界检查的版本留给 at() 成员函数——这和 std::vector 保持一致,使用者一看就懂语义差异。
v[i] → 假设调用方已校验,快;v.at(i) → 安全,抛异常operator[] 里做 at() 的事,否则失去性能优势at() 就更需要显式传入长度参数,避免误用多维容器中 proxy 的 operator[] 也应遵循同样原则:只做索引转发,不重复校验;真正检查放在 at() 或 proxy 的构造里。