CD43.vector模擬實現(2)

目錄

1.拷貝構造函數

寫法1

寫法2

測試代碼

調試找bug

解決方法:修改拷貝構造函數

測試代碼

2.operator[ ]

測試代碼

1.沒有const修飾

2.有const修飾

3.insert

迭代器失效問題


承接CD42.vector模擬實現(1)文章

1.拷貝構造函數

設置start、finish和end_of_storage這幾個參數就行,注意是深拷貝!

寫法1

vector(const vector<value_type>& x):start(0), finish(0), end_of_storage(0)
{start = new T[x.capacity()];memmove(start, x.start, x.size()*sizeof(value_type));finish = start + x.size();end_of_storage = start + x.capacity();
}

注:new的參數可以為capacity,也可以為size,這個C++標準沒有規定,空間可以不一樣,但是有效元素必須一樣

寫法2

復用reserve和memmove函數

這個代碼有問題:

vector(const vector<value_type>& x):start(0), finish(0), end_of_storage(0)
{reserve(x.capacity());memmove(start, x.start, x.size() * sizeof(value_type));
}

測試代碼

void const_vector_print(const mystl::vector<int> v)
{for (size_t i = 0;i < v.size(); i++)std::cout << v[i] << " ";
}void test6()
{mystl::vector<int> v;v.push_back(1); v.push_back(2);v.push_back(3); const_vector_print(v);return;
}

運行結果:什么都沒有打印

調試找bug

什么都沒有打印,可以判定沒有進入循環,

下斷點到循環,看看情況:

start和finish的地址一樣,v.size()計算出來為0,沒有進入循環,可以斷定拷貝構造函數出了問題,

下斷點到拷貝構造函數,再次調試:

x.capacity()計算出來是4,進入reserve函數內部:

對空的vector進行reserve,看以下分析圖:

解決方法:修改拷貝構造函數

reserve沒有更新finish,那就手動更新finish

vector(const vector<value_type>& x):start(0), finish(0), end_of_storage(0)
{reserve(x.capacity());finish = start + x.size();memmove(start, x.start, x.size() * sizeof(value_type));
}

而且標準庫也是這樣實現的:

運行結果:

同理,reserve函數也要修改:

void  reserve(size_type n)
{if (n > capacity()){T* tmp = new T[n];size_t len = size();//delete前先保存元素的個數!bool flag = false;if (size() == 0){flag = true;len = n;}memmove(tmp,start , size()* sizeof(value_type));delete[] start;if (flag)//如果vector在什么元素都沒有{start = finish = tmp;}else{start = tmp;finish = start + len;}end_of_storage = start + n;}
}

測試代碼

void test4()
{mystl::vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);mystl::vector<int> v2(v1);for (auto& a:v2)std::cout << a << " ";
}

運行結果:

2.operator[ ]

參數保持一樣的類型:

注意到返回類型被重定義過,因此先進行重定義:

typedef value_type& reference;
typedef const value_type& const_reference;

必須保證提供的n是合法的,換句話說,n<size(),可以使用assert斷言

reference operator[] (size_type n)
{assert(n < size());return *(start + n);//也可以寫成start[n]
}const_reference operator[] (size_type n) const
{assert(n < size());return *(start + n);//也可以寫成start[n]
}

測試代碼

1.沒有const修飾

void test5()
{mystl::vector<int> v;v.push_back(1); v[0]++;v.push_back(2); v[1]++;v.push_back(3); v[2]++;for (auto& a : v)std::cout << a << std::endl;return;
}

運行結果:

2.有const修飾

void const_vector_print(const mystl::vector<int> v)
{for (size_t i = 0;i < v.size(); i++)std::cout << v[i] << " ";
}void test6()
{mystl::vector<int> v;v.push_back(1); v.push_back(2);v.push_back(3); const_vector_print(v);return;
}

運行結果:

3.insert

參數保持一樣的類型,為了簡單起見,這里只實現第一個

首先要斷言,position必須合法:

assert(position >= start && position <= finish);

插入前先看看是否需要擴容,可以直接借用CD42.vector模擬實現(1)文章的push_back函數的代碼:

if (finish == nullptr)reserve(4);
if (finish == end_of_storage)reserve(capacity() * 2);

和CD38.【C++ Dev】string類的模擬實現(2)文章類似的思路,先移動再插入

迭代器失效問題

如果insert的返回值是void,

void insert(iterator position, const value_type& val)
{assert(position >= start && position <= finish);if(finish == nullptr)reserve(4);if (finish == end_of_storage)reserve(capacity() * 2);iterator i = finish-1;while (i >= position){*(i+1) = *i;i--;}*position = val;finish++;
}

頭插:

void test7()
{mystl::vector<int> v;v.push_back(1);v.push_back(2);v.insert(v.begin(), 3);return;
}

?

尾插:

void test7()
{mystl::vector<int> v;v.push_back(1);v.push_back(2);v.insert(v.end(), 3);return;
}

中間位置插入:

void test7()
{mystl::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.insert(v.begin() + 1, 4);return;
}

貌似沒有問題,但是如果是這個測試代碼:

void test7()
{mystl::vector<int> v;v.push_back(1);auto pos = v.begin();for (size_t i = 2; i <= 8; i++)v.insert(pos, i);return;
}

運行結果會出問題:?

引出迭代器失效問題

pos記錄的是原來v的start的值,如果v擴容,start的值會改變,但pos的值沒有更新,而且原先的內存空間被釋放會導致非法訪問,因此再執行v.insert(pos, i);就會出問題(即pos為野指針)

解決方法:擴容后更新pos的值,STL的解決方法:返回值為iterator

?

iterator insert(iterator position, const value_type& val)
{assert(position >= start && position <= finish);if(finish == nullptr)reserve(4);if (finish == end_of_storage)reserve(capacity() * 2);iterator i = finish-1;while (i >= position){*(i+1) = *i;i--;}*position = val;finish++;return start;
}

注:position不能引用傳參,有可能insert的第一個參數會做算術運算,例如:
?

v.insert(pos+20, i);

測試代碼:?

void test7()
{mystl::vector<int> v;v.push_back(1);auto pos = v.begin();for (size_t i = 2; i <= 8; i++)pos=v.insert(pos, i);return;
}

驗證pos是否更新:
原先:

擴容更新后:

運行結果:退出代碼為0

當然CD42.vector模擬實現(1)文章的push_back可以復用insert的代碼

1.如果不接收insert的返回值,擴容要慎重,修改可能會報錯,因為不一定擴容,所以不一定失效;

2.insert以后就不要使用原本定義的迭代器

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

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

相關文章

【C/C++】入門grpc的idl

文章目錄 grpc idl 簡單介紹1. 文件結構組織規范文件命名包結構&#xff1a;推薦&#xff1a;一個文件只定義一個 service&#xff0c;如果 service 很復雜&#xff0c;可拆分多個 proto 文件。 2. 消息定義規范命名風格字段編號&#xff1a;示例&#xff1a; 3. 服務與 RPC 設…

安全-JAVA開發-第二天

Web資源訪問的流程 由此可見 客戶訪問JAVA開發的應用時 會先通過 監聽器&#xff08;Listener&#xff09;和 過濾器&#xff08;Filter&#xff09; 今天簡單的了解下這兩個模塊的開發過程 監聽器&#xff08;Listener&#xff09; 主要是監聽 我們觸發了什么行為 并進行反應…

使用 Ansys Q3D 進行電容提取

精確的電容提取在高速和 RF 設計中至關重要。雖然簡單的公式可以提供一個很好的起點&#xff0c;但它們往往無法捕捉 fringing fields 和 layout-dependent parasitics 的影響。在本博客中&#xff0c;我們演示了如何使用Ansys Q3D Extractor來計算電容值&#xff0c;從基本的平…

卡西歐模擬器:Windows端功能強大的計算器

引言 大家還記得初中高中時期用的計算器嗎&#xff1f;今天給大家分享的就是一款windows端的卡西歐計算器。 軟件介紹 大家好&#xff0c;我是逍遙小歡。 CASIO fx-9860G是一款功能強大的圖形計算器&#xff0c;適用于數學、科學和工程計算。以下是其主要功能和特點的詳細介…

【Bluedroid】藍牙啟動之gatt_init 流程源碼解析

本文圍繞Android藍牙協議棧中 GATT(通用屬性配置文件)模塊的初始化函數gatt_init展開,深入解析其核心實現邏輯與關鍵步驟。通過分析gatt_init及其關聯子函數(如L2CA_RegisterFixedChannel、gatt_profile_db_init、EattExtension::Start等),以及相關數據結構(如tGATT_CB控…

Vue 3 中ref 結合ts 獲取 DOM 元素的實踐指南。

文章目錄 前言一、為什么需要為 ref 添加類型&#xff1f;二、基本用法&#xff1a;引用 DOM 元素1. 引用通用 DOM 元素&#xff08;HTMLElement&#xff09;2. 引用特定類型的 DOM 元素&#xff08;如 HTMLDivElement&#xff09; 三、<script setup> 語法中的類型定義四…

Axure形狀類組件圖標庫(共8套)

點擊下載《月下倚樓圖標庫(形狀組件)》 原型效果&#xff1a;https://axhub.im/ax9/02043f78e1b4386f/#g1 摘要 本圖標庫集錦精心匯集了8套專為Axure設計的形狀類圖標資源&#xff0c;旨在為產品經理、UI/UX設計師以及開發人員提供豐富多樣的設計素材&#xff0c;提升原型設計…

01串(二進制串)與集合之間存在天然的對應關系 ← bitset

【集合的二進制表示?】 ● 01 串&#xff08;二進制串&#xff09;與集合之間存在天然的對應關系。對應機理為每個二進制位可以表示集合中一個元素的存在&#xff08;1&#xff09;或不存在&#xff08;0&#xff09;。例如&#xff0c;集合 {a, b, c} 的子集 {a, c} 可以表示…

vba學習系列(10)--外觀報表

系列文章目錄 文章目錄 系列文章目錄前言一、外觀報表1.產能統計2.單板數3.固定傷排查4.件號良率5.鏡片批退率6.鏡筒批退率 總結 前言 一、外觀報表 1.產能統計 Sub ProcessInspectionData()Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As WorksheetDim lastRow1 As Long, …

machine_env_loader must have been assigned before creating ssh child instance

在主機上執行roslaunch命令時&#xff0c;報錯&#xff1a;machine_env_loader must have been assigned before creating ssh child instance。 解決辦法&#xff1a; 打開hostos文件&#xff0c;檢查local host 前的內部ip是否正常。操作示例&#xff1a; 先輸入下方指令打…

CSS radial-gradient函數詳解

目錄 基本語法 關鍵參數詳解 1. 漸變形狀&#xff08;Shape&#xff09; 2. 漸變大小&#xff08;Size&#xff09; 3. 中心點位置&#xff08;Position&#xff09; 4. 顏色斷點&#xff08;Color Stops&#xff09; 常見應用場景 1. 基本圓形漸變 2. 橢圓漸變 3. 模…

分析Web3下數據保護的創新模式

在這個信息爆炸的時代&#xff0c;我們正站在 Web3 的門檻上&#xff0c;迎接一個以去中心化、用戶主權和數據隱私為核心的新時代。Web3 不僅僅是技術的迭代&#xff0c;它更是一場關于數據權利和責任的結構性變革。本文將探討 Web3 下數據保護的創新模式&#xff0c;以期為用戶…

RabbitMQ-Go 性能分析

更多個人筆記見&#xff1a; &#xff08;注意點擊“繼續”&#xff0c;而不是“發現新項目”&#xff09; github個人筆記倉庫 https://github.com/ZHLOVEYY/IT_note gitee 個人筆記倉庫 https://gitee.com/harryhack/it_note 個人學習&#xff0c;學習過程中還會不斷補充&…

AI助力Java開發:減少70%重復編碼,實戰效能提升解析

工具再先進&#xff0c;也替代不了編程思維的深度錘煉 在Java開發領域&#xff0c;重復編碼如同無形的生產力黑洞——以商品管理模塊開發為例&#xff0c;開發者耗費大量時間編寫SQL查詢、處理結果集轉換&#xff1b;用戶系統里&#xff0c;密碼加密和狀態管理的代碼在不同項目…

JS語法筆記

目錄 JS數組Array新建數組一維數組二維數組 reverse()在數組末尾插入&#xff1a;push()在數組末尾刪除&#xff1a;pop()在數組開頭插入&#xff1a;unshift()從數組開頭刪除一個元素shift()splice() MapSet JS數組Array 判斷數組相等不能用&#xff0c;要循環判斷 新建數組…

uniapp-商城-77-shop(8.2-商品列表,地址信息添加,級聯選擇器picker)

地址信息,在我們支付訂單上有這樣一個接口,就是物流方式,一個自提,我們就顯示商家地址。一個是外送,就是用戶自己填寫的地址。 這里先說說用戶的地址添加。需要使用到的一些方式方法,主要有關于地址選擇器,就是uni-data-picker級聯選擇。 該文介紹了電商應用中地址信息處…

網頁前端開發(基礎進階3--Vue)

Vue3 Vue是一款用于構建用戶界面的漸進式的JavaScript框架。 Vue由2部分組成&#xff1a;Vue核心包&#xff0c;Vue插件包 Vue核心包包含&#xff1a;聲明式渲染&#xff0c;組件系統。 Vue插件包&#xff1a;VueRouter&#xff08;客戶端路由&#xff09;&#xff0c;Vuex…

大模型相關技術綜述

多模態大模型&大模型訓練語料持續迭代 已經開始整理多模態-視覺部分&#xff1a; 主要分為一下幾塊 多模態信息壓縮模型&#xff08;clip、vit、swiT&#xff09; 生成模型&#xff08;vae、gan、flow、ddpm、sde…) 其它多模態大模型&#xff08;語音、視頻、slam、3…

Vue3中Ant-design-vue的使用-附完整代碼

前言 首先介紹一下什么是Ant-design-vue Ant Design Vue 是基于 Vue 3 的企業級 UI 組件庫&#xff08;同時兼容 Vue 2&#xff09;&#xff0c;是螞蟻金服開源項目 Ant Design 的 Vue 實現版本。它遵循 Ant Design 的設計規范&#xff0c;提供豐富的組件和高質量的設計體系&…

建造者模式:優雅構建復雜對象

引言 在軟件開發中&#xff0c;有時我們需要創建一個由多個部分組成的復雜對象&#xff0c;這些部分可能有不同的變體或配置。如果直接在一個構造函數中設置所有參數&#xff0c;代碼會變得難以閱讀和維護。當對象構建過程復雜&#xff0c;且需要多個步驟時&#xff0c;我們可…