实现自定义vector库:如何重载[]运算符支持赋值操作?
实现可赋值的[]运算符及代码优化方案
一、实现v[index]赋值的核心方法
要支持v[2] = "2"这类赋值操作,只需重载非const版本的operator[],让它返回元素的引用(T&)——返回值作为左值,就能直接被赋值。具体代码如下:
// 非const版本,支持赋值 T& operator[](int index) { // 建议添加边界检查,避免越界访问导致未定义行为 if (index < 0 || index >= size_) { throw std::out_of_range("vector index out of range"); } return value[index]; } // 保留原const版本,支持const对象的读取操作 const T& operator[](int index) const { if (index < 0 || index >= size_) { throw std::out_of_range("vector index out of range"); } return value[index]; }
二、代码优化建议
1. 避免污染std命名空间
不要在std命名空间内自定义vector,会和标准库容器冲突,改用独立命名空间,比如:
namespace my_container { template<typename T> class vector { /* ... */ }; }
2. 规范成员变量初始化
- 用成员初始化列表替代构造函数内赋值,效率更高且符合现代C++规范;
- 用
nullptr替代NULL,类型更安全。
3. 区分size与capacity,优化扩容策略
当前代码每次push仅扩容1个元素,时间复杂度为O(n),效率极低:
- 分离
size_(实际元素个数)和capacity_(当前数组容量); - 采用倍增扩容(每次容量翻倍),将
push的均摊时间复杂度降至O(1)。
4. 修正front/back逻辑错误
原代码中front()返回最后一个元素、back()返回第一个元素,完全逻辑颠倒,正确实现应为:
T& front() { return value[0]; } const T& front() const { return value[0]; } T& back() { return value[size_ - 1]; } const T& back() const { return value[size_ - 1]; }
5. 修复reset方法的无效操作
原reset()里的vector();仅创建临时对象,不会重置当前对象的成员,应直接重置成员变量:
void reset() { delete[] value; value = nullptr; size_ = 0; capacity_ = 1; }
6. 完善内存管理(Rule of Three)
当前代码缺少析构函数、拷贝构造和拷贝赋值运算符,会导致内存泄漏或浅拷贝问题:
- 添加析构函数释放动态分配的内存;
- 实现深拷贝版本的拷贝构造与拷贝赋值(或用
delete禁用,避免浅拷贝风险)。
7. 统一添加边界检查
所有涉及索引访问的操作(operator[]、pop、front、back)都要添加边界检查,避免未定义行为。
三、优化后的完整代码
#include <iostream> #include <string> #include <stdexcept> namespace my_container { template<typename T> class vector { private: T* value = nullptr; int size_ = 0; // 实际元素个数 int capacity_ = 1; // 当前数组容量 public: // 默认构造函数 vector() = default; // 析构函数:释放动态内存 ~vector() { delete[] value; } // 拷贝构造:深拷贝实现 vector(const vector& other) { size_ = other.size_; capacity_ = other.capacity_; value = new T[capacity_]; for (int i = 0; i < size_; ++i) { value[i] = other.value[i]; } } // 拷贝赋值:深拷贝实现 vector& operator=(const vector& other) { if (this != &other) { delete[] value; size_ = other.size_; capacity_ = other.capacity_; value = new T[capacity_]; for (int i = 0; i < size_; ++i) { value[i] = other.value[i]; } } return *this; } // 返回实际元素个数 int size() const { return size_; } // 返回当前数组容量 int capacity() const { return capacity_; } // 尾部添加元素 void push(const T& val) { if (size_ == capacity_) { // 倍增扩容 capacity_ *= 2; T* temp = new T[capacity_]; for (int i = 0; i < size_; ++i) { temp[i] = value[i]; } delete[] value; value = temp; } value[size_++] = val; } // 尾部弹出元素 T pop() { if (size_ == 0) { throw std::underflow_error("vector underflow"); } T val = value[--size_]; // 可选:元素过少时缩容,避免内存浪费 if (size_ <= capacity_ / 4 && capacity_ > 1) { capacity_ /= 2; T* temp = new T[capacity_]; for (int i = 0; i < size_; ++i) { temp[i] = value[i]; } delete[] value; value = temp; } return val; } // 非const版本:支持赋值 T& operator[](int index) { if (index < 0 || index >= size_) { throw std::out_of_range("vector index out of range"); } return value[index]; } // const版本:支持const对象读取 const T& operator[](int index) const { if (index < 0 || index >= size_) { throw std::out_of_range("vector index out of range"); } return value[index]; } // 返回第一个元素 T& front() { if (size_ == 0) { throw std::out_of_range("vector is empty"); } return value[0]; } const T& front() const { if (size_ == 0) { throw std::out_of_range("vector is empty"); } return value[0]; } // 返回最后一个元素 T& back() { if (size_ == 0) { throw std::out_of_range("vector is empty"); } return value[size_ - 1]; } const T& back() const { if (size_ == 0) { throw std::out_of_range("vector is empty"); } return value[size_ - 1]; } private: // 重置容器状态 void reset() { delete[] value; value = nullptr; size_ = 0; capacity_ = 1; } }; } int main() { try { my_container::vector<std::string> v; v.push("1"); v.push("2"); v.push("3"); std::cout << "the element is : " << v[1] << "\n"; // 测试赋值操作 v[1] = "modified"; std::cout << "modified element is : " << v[1] << "\n"; std::cout << "front element is : " << v.front() << "\n"; std::cout << "back element is : " << v.back() << "\n"; std::cout << "size : " << v.size() << "\n"; std::cout << v.pop() << "\n"; std::cout << v.pop() << "\n"; std::cout << "size : " << v.size() << "\n"; v.push("4"); std::cout << "size : " << v.size() << "\n"; std::cout << v.pop() << "\n"; std::cout << "size : " << v.size() << "\n"; } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << "\n"; return 1; } return 0; }
内容的提问来源于stack exchange,提问作者satej dhakane
相关产品推荐
相关产品推荐

