C/C++ 入门(7)vector类(STL)

个人主页:仍有未知等待探索-CSDN博客

专题分栏:C++

                                                        请多多指教!

目录

一、标准库中的vector

1、了解

2、vector常用接口

二、vector的实现 

1、框架 

2、构造、析构函数

3、操作函数

三 、问题

1、由于赋值而引起的浅拷贝

2、因为类没有实例化且用了类里面声明的类型等而产生的报错

3、内部编译器错误 


一、标准库中的vector

1、了解

vector就是一个支持变长的数组。

2、vector常用接口

vector的使用不做过多强调,注重的是实现vector类。

可以点击下面的链接进入cplusplus网站,查看文档。

vector - C++ Reference

二、vector的实现 

1、框架 

#include <iostream>
#include <string>
#include <cstring>
#include <assert.h>
using namespace std;template<class T>
class vector
{
public:typedef T* iterator;//普通迭代器typedef const T* const_iterator;//const迭代器// Iterators:	iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}// 成员函数
private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;
};

2、构造、析构函数

// 无参的构造必须写,因为下面实现了构造函数,编译器不会自动生成一个无参构造函数
vector(){}
// 开辟n个大小的空间,并初始化为m
vector(const int& n, const int& m = 0)
{// 新写法(复用reserve)reserve(n);for (int i = 0; i < n; i ++ ) _start[i] = m;_finish = _start + n;
}
// 用迭代器进行构造
template<class input_iterator>
vector(input_iterator start, input_iterator end)
{input_iterator it = start;while (it != end){push_back(*it);it ++ ;}
}
// 开辟n个大小的空间,并初始化为val
// const T& val = T() -> 用一个匿名对象进行初始化,目的是为了预防vector<T>中T是一个自定义类型。
vector(size_t n, const T& val = T())
{resize(n, val);// 复用resize
}
// 用一个vector<T>进行拷贝构造
vector(const vector<T>& v)
{reserve(v.capacity());for (auto& e : v){// 复用push_back()push_back(e);}
}
// 用列表进行初始化
// vector<int> v = {1, 2, 3};
// 用库函数实现的initializer_list<T>
vector(initializer_list<T> il)
{reserve(il.size());for (auto& e : il){push_back(e);}
}
// 析构函数
~vector()
{delete[] _start;_start = _finish = _endofstorage = nullptr;
}

3、操作函数

vector<T>& operator=(vector<T> v)
{swap(v);return *this;
}
// Capacity:
size_t capacity() const
{return _endofstorage - _start;
}
size_t size() const 
{return _finish - _start;
}
bool empty() const
{return size() == 0;
}
void reserve(size_t n)
{if (capacity() < n){T* tmp = new T[n];int old_size = size();//memcpy(tmp, _start, size() * sizeof(T));// 当T是string类型的时候,memcpy会导致浅拷贝问题,并且会同时对一块空间析构多次for (int i = 0; i < old_size; i ++ ){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = tmp + old_size;_endofstorage = tmp + n;}
}
void resize(size_t n, const T& val = T())
{reserve(n);iterator it = _start;while (it != _endofstorage){*it = val;it ++ ;}
}
// Element access:
T& operator[](int pos)
{assert(pos < size());return _start[pos];
}// Modifiers:
// 在pos之前插入一个数x
void insert(iterator pos, const T& x)
{assert(pos >= _start);assert(pos <= _finish);if (_finish == _endofstorage){int len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}iterator it = _finish - 1;while (it >= pos) {*(it + 1) = *it;it -- ;}*pos = x;_finish ++ ;
}
// 尾插
void push_back(const T& x)
{// 老写法/*if (_finish == _endofstorage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;_finish ++ ;*/// 新写法insert(end() , x);
}
// 尾删
void pop_back()
{assert(!empty());_finish -- ;
}
// 交换函数,用库里面的swap实现指针的交换,来完成vector的交换
void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);
}

三 、问题

1、由于赋值而引起的浅拷贝

如果要将一个引用进行赋值,并且没有对赋值运算符重载的话,会只进行值拷贝而导致浅拷贝。最后会使编译器对同一块空间析构多次

为什么*pos,x都是T类型的,而赋值重载却写一个vector<T>类型的就能行?

因为单参数的构造函数支持隐式类型转化,编译器会先进行构造函数,将这两个值构造成对象,然后在进行赋值。

vector<T>& operator=(vector<T> v)
{swap(v);return *this;
}

2、因为类没有实例化且用了类里面声明的类型等而产生的报错

需要在使用这个类型前面加上typename标志这是一个类型。

template<class T>
void print_vector(vector<T>& v)
{// 不加typename会报错,因为在这个函数模板里,vector<T>这个类并没有实例化,会不清楚const_iterator是类型还是变量// 加typename的含义就是告诉编译器,这个是类型typename vector<T>::const_iterator it = v.begin();//auto it = v.begin();while (it != v.end()){cout << *it << " ";it ++ ;}
}

 

3、内部编译器错误 

这个错误的原因是类模板或函数模板里面有语法错误。(比如说少加了一个分号等等)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/3200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

岭回归(概念+实例)

目录 前言 一、基本概念 1. 引言 2. 岭回归的原理 3. 数学表达式 4. 岭回归的优点 5. 岭回归的局限性 6. 实际应用 二、具体实例 前言 “岭回归”这个词源于英文“Ridge Regression”&#xff0c;是一种用于处理回归分析中多重共线性&#xff08;multicollinearity&am…

Linux-软件安装--jdk安装

jdk安装 前言1、软件安装方式二进制发布包安装rpm安装yum安装源码编译安装 2、安装jdk2.1、使用finalShell自带的上传工具将jdk的二进制发布包上传到Linux2.2、解压安装包2.3、配置环境变量![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/61ba9750e2e34638a39575c5…

电脑自带dll修复在哪里打开?教你如何快速修复dll丢失问题

MSVCP140.dll文件作为Windows操作系统中不可或缺的一环&#xff0c;对众多基于C编译的应用程序的正常运行起着关键作用。在我深入研究和处理与该文件相关问题的过程中&#xff0c;积累了丰富的认知和实践经验。以下是我对MSVCP140.dll文件的总体介绍以及针对其丢失问题的解决方…

C++ 验证一下,你对递归是不是一知半解

公众号:编程驿站 公众号:编程驿站 1. 前言 无递归,不算法。无论怎样强调递归的重要性,都不为过。受限于计算机的思维能力,计算机的计算找答案的过程就是在不停试错、纠正错误的过程,类似于爱迪生发明灯炮。递归能帮助我们在不知道计算边界的情形下试错。 多函数求解过…

echarts树图-实现拓扑图效果

使用echarts树图来实现拓扑图效果&#xff0c;其效果如下&#xff1a; 代码如下&#xff1a; const data {name: XXX公司,children: [{name: 网络主机,children: [{name: 普通路由器,children: [{name: 智能网关},{name: 192.168.1.0/24}]}]},{name: 企业路由器},{name: 三…

MySQL-----多表查询(一)

目录 一.多表关系&#xff1a; 1.1 一对多(多对一)&#xff1a; 1.2 多对多: 1.3 一对一: 二.多表查询概述&#xff1a; 三.连接查询&#xff1a; 3.1内连接&#xff1a; 3.2外连接&#xff1a; 3.3自连接查询&#xff1a; 3.4联合查询&#xff1a; 一.多表关系&…

Vast+产品展厅 | Vastbase G100数据库是什么架构?(1)

Vastbase G100是海量数据融合了多年对各行业应用场景的深入理解&#xff0c;基于openGauss内核开发的企业级关系型数据库。 了解Vastbase G100的架构&#xff0c;可以帮助您确保数据库系统的高效、可靠和安全运行。 “Vast产品展厅”将分两期&#xff0c;为您详细讲解Vastbas…

划分数据集2,详细说明

看完了这个之后划分数据集&#xff0c;训练自己的数据集。-CSDN博客 我再详细说一下自己标注的文件放在什么位置 我发的文件里有这几个文件 在dataset里面有 自己的数据集分为&#xff0c;图片部分和标注文件部分 打开VOCdevkit文件夹 里面有三个文件夹 自己的图片的话&…

(C++) 内类生成智能指针shared_from_this介绍

文章目录 &#x1f601;介绍&#x1f914;类外操作&#x1f605;错误操作&#x1f602;正确操作 &#x1f914;类内操作&#x1f62e;std::enable_shared_from_this<>&#x1f62e;奇异递归模板 CRTP&#xff08;Curiously Recurring Template Pattern&#xff09;&#…

carrier开利触摸屏ICVC控制面板维修CEPL130445

开利离心机19XR空调ICVC显示面板维修CEPL130445-03-R/04-R/02-R 人机界面触摸维修故障有&#xff1a;花屏、白屏、按触摸屏无反应或反应慢(触摸不好)、内容错乱、无背光、背光暗、有背光无字符、不能通信、按键无反应等&#xff08;可更换液晶屏&#xff09;黑屏、对触摸屏触摸…

QML 中的状态

Qt hello – 专注于Qt的技术分享平台 状态描述了当前用户界面样子&#xff0c;QML中一个状态定义了一组属性的改变&#xff0c;并且会在一定条件下被触发。 假设有这么一个场景&#xff0c;红黄绿三个灯&#xff0c;用一个按钮&#xff0c;点击后依次切换三个灯亮起。使用QWi…

js如何获取对象的属性值

获取对象的属性值&#xff0c;有两种方式。 方式一&#xff1a; 对象.属性名 let obj {name:张三,age:23 }; console.log(obj.name); //张三方式二&#xff1a; 对象[属性名] let obj {name:张三,age:23 }; console.log(obj[name]); //张三 两种方式有什么不同&am…

AWR报告采集

一、windows下采集 自动负载信息库&#xff08;Automatic Workload Repository&#xff0c;AWR&#xff09;是在Oracle 10g中被引入的&#xff0c;缺省地被安装到Oracle10g数据库中&#xff0c;用于收集关于该特定数据库的操作统计信息和其他统计信息。AWR的采样工作由后台进程…

Linux-线程互斥和死锁

目录 一.线程互斥 1.1 进程线程间的互斥相关背景概念 1.2 互斥量mutex 二.互斥量的接口 2.1 初始化互斥量 2.2 销毁互斥量 2.3 互斥量加锁和解锁 2.4 改进后售票代码 三.死锁 3.1.什么是死锁&#xff1f; 3.2.死锁四个必要条件 3.3 避免死锁 一.线程互斥 1.1 进程…

吴恩达2022机器学习专项课程(一) 6.1 动机第三周课后实验:Lab1使用逻辑回归进行分类

问题预览/关键词 什么是逻辑回归&#xff1f;什么是二分类问题&#xff1f;二分类问题案例如何表达二分类的结果&#xff1f;逻辑回归通常用哪种表达形式&#xff1f;什么是正样本和负样本&#xff1f;什么是阈值&#xff1f;可视化线性回归解决二分类线性回归面对二分类产生的…

jmeter之跨线程关联

1&#xff09;_setproperty函数&#xff1a;将值保存成jmeter属性 2&#xff09;_property函数&#xff1a;在其他线程组中使用property函数读取属性 一、跨线程接口引用变量 1. 法一&#xff1a;jmeter自带函数_setProperty和_property 1. 1线程组 01 创建登录的【HTTP请求】…

1、k8s问题pod从service中剔除

一、起因 redis原来由两服务器的集群变为三服务器的集群&#xff0c;通过statefulset扩展了两节点&#xff0c;并把redis-app-0和redis-app-3从集群中去除&#xff0c;但是由于service路由后端不变&#xff0c;导致程序连接后端仍然可能到redis-app-0和redis-app-3 二、处理 …

分类算法——决策树(五)

认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-else结构&#xff0c;最早的决策树就是利用这类结构分割数据的一种分类学习方法。 决策树分类原理详解 为了更好理解决策树具体怎么分类的&#xff0c;通过一个问题例子&#xff1a; 问题…

C++入门----内联函数auto范围fornullptr指针

1.内联函数 顾名思义&#xff0c;内联函数也是函数的一种&#xff0c;我们在C语言的学习过程里面知道了函数和宏之间的区别和各自的优缺点&#xff1b; 函数的使用需要建立栈帧&#xff0c;宏的使用需要考虑各种符号的优先级问题&#xff0c;很容易出错&#xff0c;因为宏在使…

HarmonyOS开发案例:【闹钟】

介绍 使用后台代理提醒&#xff0c;实现一个简易闹钟。要求完成以下功能&#xff1a; 展示指针表盘或数字时间。添加、修改和删除闹钟。展示闹钟列表&#xff0c;并可打开和关闭单个闹钟。闹钟到设定的时间后弹出提醒。将闹钟的定时数据保存到轻量级数据库。 相关概念 [Canva…