实现一个安全向量模板类 SiVector,其设计目标是:在保持 std::vector 易用性的基础上,增强越界访问的安全性(避免崩溃),同时兼容 std::vector 的核心接口和使用习惯。支持嵌套使用(如 SiVector<std::vector<double>>),提供越界访问时的默认值返回或自动扩容机制,并支持与 std::vector 的双向类型转换。

实现

代码示例

#include <string>
  #include <iostream>
    #include <vector>
      #include <iterator>
        template <
        typename T>
        class SiVector
        {
        public:
        SiVector(T value) : m_defaultValue(value) {
        }
        SiVector(std::vector<T> data) : m_datas(data) {
          }
          SiVector(std::vector<T> data, T value) : m_datas(data), m_defaultValue(value) {
            }
            // ========== 构造函数:模仿std::vector ==========
            SiVector() : m_defaultValue(T()) {
            }
            // 构造指定大小的容器,元素初始化为value(默认用默认值)
            explicit SiVector(uint32_t size, const T& value = T())
            : m_datas(size, value), m_defaultValue(T()) {
            }
            // 从迭代器范围构造
            template <
            typename InputIt>
            SiVector(InputIt first, InputIt last)
            : m_datas(first, last), m_defaultValue(T()) {
            }
            // 从初始化列表构造(支持 SiVector<int> v = {1,2,3};)
              SiVector(std::initializer_list<T> init)
                : m_datas(init), m_defaultValue(T()) {
                }
                // 拷贝构造
                SiVector(const SiVector& other) = default;
                // 移动构造
                SiVector(SiVector&& other) noexcept = default;
                // 类型别名:模仿std::vector的迭代器类型
                // using value_type = T;
                using iterator = typename std::vector<T>
                  ::iterator;
                  using const_iterator = typename std::vector<T>
                    ::const_iterator;
                    // using reference = T&;
                    // using const_reference = const T&;
                    // using size_type = size_t;
                    // ========== 赋值操作:模仿std::vector ==========
                    SiVector&
                    operator=(const SiVector& other) = default;
                    SiVector&
                    operator=(SiVector&& other) noexcept = default;
                    SiVector&
                    operator=(std::initializer_list<T> init) {
                      m_datas = init;
                      return *this;
                      }
                      // 重载[]:越界时返回默认值(const版)
                      T&
                      operator[](uint32_t index) {
                      if (index >= m_datas.size()) {
                      std::cout <<
                      "index out of range. ";
                      m_datas.resize(index + 1, m_defaultValue);
                      }
                      return m_datas[index];
                      }
                      const T&
                      operator[](uint32_t index) const {
                      if (index >= m_datas.size()) {
                      std::cout <<
                      "index out of range. ";
                      return m_defaultValue;
                      }
                      return m_datas[index];
                      }
                      T&
                      at(uint32_t index) {
                      if (index >= m_datas.size()) {
                      std::cout <<
                      "at index out of range. ";
                      return m_defaultValue;
                      }
                      return m_datas[index];
                      }
                      const T&
                      at(uint32_t index) const {
                      if (index >= m_datas.size()) {
                      std::cout <<
                      "at index out of range. ";
                      return m_defaultValue;
                      }
                      return m_datas[index];
                      }
                      // 首尾元素访问
                      T&
                      front() {
                      return m_datas.front();
                      }
                      const T&
                      front() const {
                      return m_datas.front();
                      }
                      T&
                      back() {
                      return m_datas.back();
                      }
                      const T&
                      back() const {
                      return m_datas.back();
                      }
                      // ========== 迭代器:支持范围for循环 ==========
                      iterator begin() noexcept {
                      return m_datas.begin();
                      }
                      // const_iterator const begin() noexcept { return m_datas.begin(); }
                      const_iterator const cbegin() noexcept {
                      return m_datas.cbegin();
                      }
                      iterator end() noexcept {
                      return m_datas.end();
                      }
                      // const_iterator const end() noexcept { return m_datas.end(); }
                      const_iterator const cend() noexcept {
                      return m_datas.cend();
                      }
                      // ========== 容量操作:与std::vector一致 ==========
                      bool empty() const noexcept {
                      return m_datas.empty();
                      }
                      uint32_t const size() noexcept {
                      return m_datas.size();
                      }
                      uint32_t capacity() const noexcept {
                      return m_datas.capacity();
                      }
                      // 调整大小(多余元素用默认值填充)
                      void resize(uint32_t size) { m_datas.resize(size, m_defaultValue);
                      }
                      void resize(uint32_t size , const T& value) { m_datas.resize(size, value);
                      }
                      // 预留容量
                      void reserve(uint32_t size) { m_datas.reserve(size);
                      }
                      void shrink_to_fit() { m_datas.shrink_to_fit();
                      }
                      operator std::vector<T>() const {
                        return m_datas;
                        }
                        // ========== 修改操作:与std::vector一致 ==========
                        void push_back(const T& value) { m_datas.push_back(value);
                        }
                        void push_back(T&& value) { m_datas.push_back(std::move(value));
                        }
                        template <
                        typename... Args>
                        T&
                        emplace_back(Args&&
                        ... args) {
                        return m_datas.emplace_back(std::forward<Args>(args)...);
                          } // std::forward<Args>(args)... 中的 ... 是必须的,它的作用是:将参数包 args 中的所有参数逐个展开,传递给 m_datas.emplace_back. 保持每个参数的转发语义(完美转发)
                            void pop_back() {
                            if (!m_datas.empty()) {
                            m_datas.pop_back();
                            }
                            }
                            // 插入元素(在pos位置插入value)
                            iterator insert(const iterator pos, const T& value) {
                            return m_datas.insert(pos, value);
                            }
                            iterator insert(const iterator pos, uint32_t size, const T& value) {
                            return m_datas.insert(pos, size, value);
                            }
                            // 清除元素
                            void clear() noexcept {
                            m_datas.clear();
                            }
                            // 交换两个容器
                            void swap(SiVector& other) noexcept {
                            m_datas.swap(other.m_datas);
                            std::swap(m_defaultValue, other.m_defaultValue);
                            }
                            operator std::vector<std::vector<T>>() const {
                              std::vector<std::vector<T>> result;
                                for (uint32_t i = 0; i< m_datas.size(); i++) {
                                result.push_back(m_datas[i]);
                                }
                                return result;
                                }
                                void setDefault(const T& defaultValue) {
                                m_defaultValue = defaultValue;
                                }
                                private:
                                std::vector<T> m_datas;
                                  T m_defaultValue{
                                  0
                                  };
                                  };
                                  int main() {
                                  std::vector<std::vector<
                                  double>> data{
                                  {
                                  0.2, 0.5
                                  }, {
                                  0.4, 100.5, 100.6
                                  }
                                  };
                                  SiVector<std::vector<
                                  double>>
                                  vec(data);
                                  uint32_t index = 0;
                                  for (auto it : vec) {
                                  std::cout <<
                                  "index[" << index <<
                                  "]" << std::endl;
                                  index++;
                                  for (const auto& in : it) {
                                  std::cout <<
                                  "value : " << in << std::endl;
                                  }
                                  }
                                  std::vector<std::vector<
                                  double>> vec1 = vec;
                                  index = 0;
                                  for (auto it : vec1) {
                                  std::cout <<
                                  "index[" << index <<
                                  "]" << std::endl;
                                  index++;
                                  for (const auto& in : it) {
                                  std::cout <<
                                  "value : " << in << std::endl;
                                  }
                                  }
                                  std::cout << vec[10000][5000] << std::endl;
                                  std::vector<
                                  double> vec2 = vec[3];
                                  // 访问vec2[5]有可能崩溃
                                  std::cout << vec2[5] << vec2.size() << std::endl;
                                  return 1;
                                  }

重点解释

1. 类定义与模板基础
template <
typename T>
class SiVector
{
...
};
  • template <typename T>:模板类定义,使 SiVector 支持任意数据类型(如 intdoublestd::vector<double> 等),具备通用性。
  • 核心成员:
    • m_datas:内部使用 std::vector<T> 存储数据,复用标准容器的内存管理逻辑;
    • m_defaultValue:越界访问时返回的默认值(通过 setDefault 可自定义)。
2. 构造函数:兼容 std::vector 的初始化方式

SiVector 提供了多种构造函数,覆盖 std::vector 的常见初始化场景:

// 无参构造
SiVector() : m_defaultValue(T()) {
}
// 指定大小和初始值构造(explicit避免隐式类型转换)
explicit SiVector(uint32_t size, const T& value = T())
: m_datas(size, value), m_defaultValue(T()) {
}
// 迭代器范围构造(支持从其他容器复制元素)
template <
typename InputIt>
SiVector(InputIt first, InputIt last)
: m_datas(first, last), m_defaultValue(T()) {
}
// 初始化列表构造(支持 SiVector<int> v = {1,2,3}; 语法)
  SiVector(std::initializer_list<T> init)
    : m_datas(init), m_defaultValue(T()) {
    }
    // 拷贝构造与移动构造(=default 复用编译器默认实现)
    SiVector(const SiVector& other) = default;
    SiVector(SiVector&& other) noexcept = default;
  • explicit:修饰单参数构造函数,避免意外的隐式类型转换(如 SiVector<int> v = 5; 会编译报错,需显式构造)。
  • = default:对拷贝/移动构造使用默认实现,编译器会自动生成“逐成员拷贝/移动”的逻辑,简洁高效。
3. 元素访问:安全的 operator[]at()

SiVector 的核心安全特性体现在元素访问接口,解决了 std::vector 越界访问崩溃的问题:

(1)operator[] 重载
// 非const版本:越界时自动扩容(保证修改操作安全)
T&
operator[](uint32_t index) {
if (index >= m_datas.size()) {
std::cout <<
"index out of range. ";
m_datas.resize(index + 1, m_defaultValue);
// 扩容并填充默认值
}
return m_datas[index];
}
// const版本:越界时返回默认值(只读场景不修改容器)
const T&
operator[](uint32_t index) const {
if (index >= m_datas.size()) {
std::cout <<
"index out of range. ";
return m_defaultValue;
// 不扩容,返回默认值
}
return m_datas[index];
}
  • 核心逻辑:通过 index >= m_datas.size() 检查越界,非const对象越界时自动扩容(确保后续访问有效),const对象越界时返回默认值(避免修改const对象)。
  • 优势:既避免了 std::vector::operator[] 越界导致的未定义行为(崩溃/数据错乱),又保持了类似数组的便捷访问语法。
(2)at() 方法
T&
at(uint32_t index) {
if (index >= m_datas.size()) {
std::cout <<
"at index out of range. ";
return m_defaultValue;
// 越界返回默认值(与std::vector::at()抛异常不同)
}
return m_datas[index];
}
  • std::vector::at() 不同:std::vector::at() 越界会抛出 std::out_of_range 异常,而 SiVector::at() 越界返回默认值,进一步避免程序终止。
4. 迭代器:支持范围for循环
// 类型别名:复用std::vector的迭代器类型
using iterator = typename std::vector<T>
  ::iterator;
  using const_iterator = typename std::vector<T>
    ::const_iterator;
    // 迭代器接口
    iterator begin() noexcept {
    return m_datas.begin();
    }
    const_iterator cbegin() noexcept {
    return m_datas.cbegin();
    }
    iterator end() noexcept {
    return m_datas.end();
    }
    const_iterator cend() noexcept {
    return m_datas.cend();
    }
  • 作用:通过提供 begin()/end() 等迭代器接口,SiVector 支持 C++ 范围for循环(for (auto x : vec) { ... }),语法与 std::vector 完全一致。
  • 实现逻辑:直接复用内部 m_datasstd::vector)的迭代器,无需手动实现迭代器逻辑,简化代码且保证兼容性。
5. 容量管理:与 std::vector 行为一致
// 容量操作
uint32_t const size() noexcept {
return m_datas.size();
} // 实际元素数量
uint32_t capacity() const noexcept {
return m_datas.capacity();
} // 已分配内存容量
void resize(uint32_t size) { m_datas.resize(size, m_defaultValue);
} // 调整大小(填充默认值)
void reserve(uint32_t size) { m_datas.reserve(size);
} // 预分配容量(不改变大小)
void shrink_to_fit() { m_datas.shrink_to_fit();
} // 收缩容量至实际大小
  • 这些接口与 std::vector 功能完全一致,确保用户可以像管理 std::vector 一样管理 SiVector 的内存(如预分配容量提升性能、收缩容量节省内存)。
6. 类型转换:与 std::vector 双向兼容

SiVector 定义了类型转换运算符,支持与 std::vector 无缝转换:

// 转换为单层std::vector<T>
operator std::vector<T>() const {
  return m_datas;
  }
  // 转换为嵌套std::vector<std::vector<T>>(针对嵌套SiVector)
  operator std::vector<std::vector<T>>() const {
    std::vector<std::vector<T>> result;
      for (uint32_t i = 0; i < m_datas.size(); i++) {
      result.push_back(m_datas[i]);
      }
      return result;
      }
  • 使用场景:当需要调用接受 std::vector 参数的函数时,SiVector 对象可自动转换为 std::vector,无需手动拷贝(如 std::vector<std::vector<double>> vec1 = vec;)。
7. 修改操作:高效元素添加/删除
// 尾部添加元素(支持拷贝和移动语义)
void push_back(const T& value) { m_datas.push_back(value);
}
void push_back(T&& value) { m_datas.push_back(std::move(value));
}
// 原地构造元素(避免拷贝,高效)
template <
typename... Args>
T&
emplace_back(Args&&
... args) {
return m_datas.emplace_back(std::forward<Args>(args)...);
  }
  • emplace_back 与完美转发
    • Args&&... args 是可变参数模板(参数包),支持任意数量和类型的参数;
    • std::forward<Args>(args)... 中的 ... 用于展开参数包,将参数“完美转发”给 m_datas.emplace_back,实现元素在容器内部直接构造(无需临时对象拷贝),性能优于 push_back
8. main 函数示例解析
int main() {
// 1. 初始化嵌套SiVector(从std::vector<std::vector<double>>构造)
  std::vector<std::vector<
  double>> data{
  {
  0.2, 0.5
  }, {
  0.4, 100.5, 100.6
  }
  };
  SiVector<std::vector<
  double>>
  vec(data);
  // 2. 范围for循环遍历(依赖迭代器实现)
  for (auto it : vec) {
  ...
  }
  // 3. 转换为std::vector并遍历
  std::vector<std::vector<
  double>> vec1 = vec;
  // 4. 越界访问测试(非const版本自动扩容)
  std::cout << vec[10000][5000] << std::endl;
  // 外层越界自动扩容,内层同理
  // 5. 验证转换后的std::vector越界行为(可能崩溃,体现SiVector的安全性)
  std::vector<
  double> vec2 = vec[3];
  std::cout << vec2[5] << vec2.size() << std::endl;
  // std::vector越界是未定义行为
  }
  • 示例展示了 SiVector 的核心特性:嵌套使用、范围遍历、类型转换、安全越界访问,同时对比了 std::vector 越界的风险,突出 SiVector 的安全性。

总结

SiVector 通过以下设计实现了“安全”与“兼容”的平衡:

  1. 安全访问operator[]at() 越界时返回默认值或自动扩容,避免崩溃;
  2. 接口兼容:模仿 std::vector 的构造函数、迭代器、容量管理接口,降低使用成本;
  3. 高效转换:支持与 std::vector 双向转换,兼容标准库生态;
  4. 性能优化:通过 emplace_back 完美转发和复用 std::vector 内存管理,保证效率。

适用于需要频繁访问元素且对稳定性要求高的场景。

posted on 2025-09-23 09:19  lxjshuju  阅读(12)  评论(0)    收藏  举报