安全向量模板類SiVector

實現一個安全向量模板類 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 內存管理,保證效率。

適用于需要頻繁訪問元素且對穩定性要求高的場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920344.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920344.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920344.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Cloudflare 推出 GenAI 安全工具,守護企業數據

8 月 26 日,Cloudflare 為其企業平臺 Cloudflare One 推出了新的安全功能,幫助企業安全地采用 ChatGPT、Claude 和 Gemini 等生成式 AI 工具。該工具構建為云訪問安全代理 (CASB),通過 API 集成來監控和保護這些 AI 服務,無需安裝設備。 隨著企業對 GenAI 的使用激增——C…

Mac測試端口連接的幾種方式

在 macOS 上測試端口是否開放&#xff0c;可通過以下三種常用方法實現&#xff08;推薦優先使用系統自帶的 nc 命令&#xff0c;簡單高效&#xff09;&#xff1a;方法 1&#xff1a;用系統自帶 nc&#xff08;netcat&#xff09;測試&#xff08;最推薦&#xff09;nc 是 macO…

用PyTorch實現多類圖像分類:從原理到實際操作

引言 圖像分類作為計算機視覺的基石&#xff0c;已深度滲透到我們生活的方方面面——從醫療影像中早期腫瘤的識別、自動駕駛汽車對道路元素的實時檢測&#xff0c;到衛星圖像的地形分析與零售行業的商品識別&#xff0c;其核心都是讓機器學會"看懂"世界并做出分類決…

window安裝python環境

1、確認操作系統類型和位數&#xff0c;明確下載安裝包的版本&#xff0c;示例為&#xff1a;windows&#xff0c;64位環境。 2、登錄python官網下載exe安裝包&#xff0c;下載網址&#xff1a;Download Python | Python.org 找到想要的對應python版本&#xff0c;本次示例下…

用 Streamlit 構建一個簡易對話機器人 UI

在這篇文章中&#xff0c;我將演示如何用 Streamlit 快速構建一個輕量的對話機器人 UI&#xff0c;并通過 LangChain / LangGraph 調用 LLM&#xff0c;實現簡單的對話功能。通過將前端和后端分離&#xff0c;你可以單獨測試模型調用和 UI 顯示。為什么選擇 Streamlit&#xff…

【Redis 進階】Redis 典型應用 —— 緩存(cache)

一、什么是緩存 緩存&#xff08;cache&#xff09;是計算機中的一個經典的概念&#xff0c;在很多場景中都會涉及到。核心思路就是把一些常用的數據放到觸手可及&#xff08;訪問速度更快&#xff09;的地方&#xff0c;方便隨時讀取。 舉例&#xff1a;我需要去高鐵站坐高鐵…

RK3588 Ubuntu22.04 解決eth0未托管問題

在調試rk3588的Ubuntu的時候發現&#xff0c;網絡那里一直顯示eth0未托管&#xff0c;但是聯網功能又是正常的&#xff0c;猜測是某一個配置文件的問題修改如下&#xff1a;打開/etc/NetworkManager/NetworkManager.conf&#xff0c;將managed&#xff0c;修改成true即可然后重…

雷卯針對香橙派Orange Pi 3G-IoT-B開發板防雷防靜電方案

一、應用場景計算機、無線網絡服務器、游戲機、音樂播放器、高清視頻播放器、揚聲器、Android 設備、Scratch 編程平臺二、核心功能參數三、擴展接口詳情雷卯專心為您解決防雷防靜電的問題&#xff0c;有免費實驗室供檢測。開發板資料轉自深圳迅龍軟件。謝謝&#xff01;

Science Robotics 豐田研究院提出通過示例引導RL的全身豐富接觸操作學習方法

人類表現出非凡的能力&#xff0c;可以利用末端執行器&#xff08;手&#xff09;的靈巧性、全身參與以及與環境的交互&#xff08;例如支撐&#xff09;來縱各種大小和形狀的物體。 人類靈活性的分類法包括精細和粗略的作技能。盡管前者&#xff08;精細靈巧性&#xff09;已在…

趣丸游戲招高級業務運維工程師

高級業務運維工程師趣丸游戲 廣州職位描述1、負責公司AI業務線運維工作&#xff0c;及時響應、分析、處理問題和故障&#xff0c;保證業務持續穩定&#xff1b; 2、負責基于分布式、微服務、容器云等復雜業務的全生命周期的穩定性保障&#xff1b; 3、參與設計運維平臺、工具、…

2025通用證書研究:方法論、崗位映射與四證對比

本文基于公開材料與典型招聘描述&#xff0c;對常見通用型或準入型證書做方法論級別的比較&#xff0c;不構成培訓或報考建議&#xff0c;也不涉及任何招生、返現、團購等信息。全文采用統一術語與可復用模板&#xff0c;以減少“經驗之爭”&#xff0c;便于不同背景的讀者獨立…

在WSL2-Ubuntu中安裝Anaconda、CUDA13.0、cuDNN9.12及PyTorch(含完整環境驗證)

WSL 搭建深度學習環境&#xff0c;流程基本上是一樣的&#xff0c;完整細節可參考我之前的博客&#xff1a; 在WSL2-Ubuntu中安裝CUDA12.8、cuDNN、Anaconda、Pytorch并驗證安裝_cuda 12.8 pytorch版本-CSDN博客 之所以記錄下來&#xff0c;是因為CUDA和cuDNN版本升級后&#x…

OpenFOAM中梯度場的復用(caching)和生命期管理

文章目錄OpenFOAM中梯度場的復用(caching)和生命期管理一、緩存機制的目標二、如何實現緩存&#xff08;以 fvc::grad 為例&#xff09;1. 使用 IOobject::AUTO_WRITE 和注冊名2. 示例&#xff1a;fvc::grad 的緩存實現&#xff08;簡化邏輯&#xff09;三、生命期管理是如何實…

【Hot100】貪心算法

系列文章目錄 【Hot100】二分查找 文章目錄系列文章目錄方法論Hot100 之貪心算法121. 買賣股票的最佳時機55. 跳躍游戲45. 跳躍游戲 II763. 劃分字母區間方法論 Hot100 之貪心算法 121. 買賣股票的最佳時機 121. 買賣股票的最佳時機&#xff1a;給定一個數組 prices &#…

電子電氣架構 --- 軟件項目復雜性的駕馭思路

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

SSE實時通信與前端聯調實戰

1.SSE 原理機制 sse 類似websocket,但是sse是單向的&#xff0c;不可逆的&#xff0c;只能服務端向客戶端發送數據流 2.解決跨域問題 Access to XMLHttpRequest at http://127.0.0.1:8090/sse/doChat from origin http://127.0.0.1:3000 has been blocked by CORS policy: Re…

從傳統到創新:用報表插件重塑數據分析平臺

一、傳統 BI 平臺面臨的挑戰 在當今數字化時代&#xff0c;數據已成為企業決策的重要依據。傳統的商業智能&#xff08;BI&#xff09;平臺在數據處理和分析方面發揮了重要作用&#xff0c;但隨著數據量的爆炸式增長和用戶需求的日益多樣化&#xff0c;其局限性也逐漸顯現。 …

MySQL--MySQL中的DECIMAL 與 Java中的BigDecimal

1. 為什么需要 DECIMAL在數據庫中&#xff0c;常見的數值類型有&#xff1a;INT、BIGINT → 整數&#xff0c;存儲容量有限。FLOAT、DOUBLE → 浮點數&#xff0c;存儲效率高&#xff0c;但存在精度丟失問題。DECIMAL(M, D) → 定點數&#xff0c;存儲精確值。例子&#xff1a;…

低空無人機系統關鍵技術與應用前景:SmartMediaKit視頻鏈路的基石價值

引言&#xff1a;低空經濟的新興格局 低空經濟作為“新質生產力”的代表&#xff0c;正在從政策驅動、技術突破和市場需求的共振中走向產業化。2023年&#xff0c;中國低空經濟的市場規模已超過 5000 億元人民幣&#xff0c;同比增長超過 30%。無人機&#xff08;UAV&#xff…

在Windows系統上升級Node.js和npm

在Windows系統上升級Node.js和npm&#xff0c;我推薦以下幾種方法&#xff1a; 方法1&#xff1a;使用官網安裝包&#xff08;最簡單&#xff09; 訪問 nodejs.org 下載Windows安裝包&#xff08;.msi文件&#xff09; 運行安裝包&#xff0c;選擇"修復"或直接安裝新…