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.mfbz.cn/a/573366.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【linux】多路径|Multipath I/O 技术

目录 简略 详细 什么是多路径? Multipath安装与使用 安装 使用 Linux下multipath软件介绍 附录 配置文件说明 其他解 简略 略 详细 什么是多路径? 普通的电脑主机都是一个硬盘挂接到一个总线上&#xff0c;这里是一对一的关系。 而到了分布式环境&#xff0c;主机和存储网络连…

普冉PY32F071单片机简单介绍,QFN64 48封装,支持 8 * 36 / 4 * 40 LCD

PY32F071单片机是一款基于32 位 ARM Cortex - M0内核的微控制器&#xff0c;由普冉半导体推出。PY32F071可广泛应用于各种嵌入式系统中&#xff0c;包括消费类电子产品、工业自动化、医疗设备等领域。PY32F071系列单片机具有低功耗、高性能和丰富的外设接口等特点&#xff0c;适…

生物制药企业在选择文件摆渡平台时,最应该关注哪些功能?

生物制药是以数据为核心生产力的企业&#xff0c;数据的重要性体现在药物研发、生产优化、销售和市场营销、决策支持以及合规要求等多个方面。有效地管理和利用数据&#xff0c;对于提升企业的竞争力、降低风险、提高产品质量和满足市场需求具有重要意义。 为保护数据安全&…

KEITHLEY(吉时利)2440源测量单位(SMU)数字源表

KEITHLEY(吉时利&#xff09;2440源测量单位&#xff08;SMU)数字源表 主要特性 50W 时性能高达 5A / 40V0.012&#xff05; 基本测量精度&#xff0c;具有 6 位分辨率10pA / 100nV 测量分辨率与 KickStart 软件结合使用美国2440吉时利keithley数字源表特点 2400系列提供宽动…

亚信安慧AntDB:高效与稳定

亚信安慧AntDB正致力于验证数据库软硬件全自主可控的可行性&#xff0c;并将其应用于运营商核心的交易场景&#xff0c;以替代国外商业解决方案。为了实现这一目标&#xff0c;亚信安慧AntDB的研发团队不断进行技术创新和实践探索。 该数据库以自主研发的技术为基础&#xff0…

C语言 流程图与伪代码 缩减

本文 我们来说说流程图 伪代码和代码缩进 这些可以让我们在后面书写复杂逻辑时 不会感到 繁琐或逻辑混乱 流程图(Flowchart) 是用以算法、工作流或流程的一种框图表示&#xff0c;它以不同类型的框代表不同种类的步骤&#xff0c;每两个步骤之间则以箭头连接。 流程图是程序…

《飞吧龙骑士》新版本“龙神祭”盛大开启,引领骑士团战

热游圈消息&#xff1a;五一假期临近&#xff0c;备受瞩目的手游《飞吧龙骑士》迎来重大更新——“龙神祭”新版本正式开启。在此次更新中&#xff0c;首个蓄力炮UR龙——绮舞的巫女千代烬惊艳登场&#xff0c;为玩家们带来前所未有的燃情体验。同时&#xff0c;全新骑士团战玩…

当你看到一份更心仪的工作时,先冷静冷静,看看这篇文章

01 无法构建自己的城堡&#xff1f;那就挖一条护城河 人活一辈子&#xff0c;在职业生涯领域&#xff0c;你总得要搭建一座属于自己的城堡&#xff0c;否则拼死拼活&#xff0c;到最后你拿到一点蝇头小利&#xff0c;为别人做嫁衣。而当别人的梦想进行曲不需要你合奏或者伴奏时…

从现在开始:让AI写代码,你只负责敲tab键

如果你是一名程序员&#xff0c;你一定有过这样的经历&#xff1a;在编写代码的时候&#xff0c;突然遇到了一个棘手的问题&#xff0c;需要花费大量的时间去查找资料、尝试不同的解决方案&#xff0c;甚至有时候还需要去问同事或者在网上寻求帮助。这样的情况不仅会浪费你的时…

【算法刷题 | 贪心算法03】4.25(最大子数组和、买卖股票的最佳时机|| )

文章目录 4.最大子数组和4.1题目4.2解法一&#xff1a;暴力4.2.1暴力思路4.2.2代码实现 4.3解法二&#xff1a;贪心4.3.1贪心思路4.3.2代码实现 5.买卖股票的最佳时机||5.1题目5.2解法&#xff1a;贪心5.2.1贪心思路5.2.2代码实现 4.最大子数组和 4.1题目 给你一个整数数组 n…

Linux中DHCP原理与配置

目录 一.DHCP的原理 1.DHCP的简要概述 2.DHCP的优点 3.DHCP的分配方式 4.DHCP的租约过程 5.DHCP服务 6.可分配的地址信息主要包括 二.DHCP同一网段分配地址实验 windows命令 一.DHCP的原理 1.DHCP的简要概述 DHCP&#xff08;Dynamic Host Configuration Protocol&a…

讯鹏智慧公厕系统解决方案新升级,大不同!

在城市建设和公共服务不断发展的今天&#xff0c;公厕作为重要的基础设施&#xff0c;其质量和管理水平直接影响着人们的生活体验。然而&#xff0c;当前公厕普遍存在着一些问题&#xff0c;如卫生状况不佳、设施老化、管理不便等。为了解决这些问题&#xff0c;讯鹏智慧公厕系…

牛客NC209 最短无序连续子数组【中等 数组,双指针 C++/Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/d17f4abd1d114617b51e951027be312e 思路 解题思路 1、方法1&#xff0c;排序对比&#xff1a;将数组按升序排序&#xff0c;然后与原数组对照&#xff0c;从哪里开始变化到哪里结束变化的数组就是答案。 2、 方…

图像处理技术与应用(二)

图像处理技术与应用入门 椒盐噪声 椒盐噪声&#xff0c;也称为脉冲噪声&#xff0c;是一种常见的数字图像噪声。它通常表现为图像中随机出现的白色&#xff08;椒&#xff09;或黑色&#xff08;盐&#xff09;像素点&#xff0c;这些像素点在图像上呈现为黑白杂点。椒盐噪声…

云计算革新:以太网 Scale-UP 网络为 GPU 加速赋能

谈谈基于以太网的GPU Scale-UP网络 Intel Gaudi-3 采用 RoCE 互联技术&#xff0c;促进了 Scale-UP 解决方案。业界专家 Jim Keller 倡导以太网替代 NVLink。Tenstorrent 成功应用以太网实现片上网络互联。RoCE 和以太网已成为互联解决方案的新兴趋势&#xff0c;为高性能计算提…

前端H5动态背景登录页面(下)

最近正好有点儿时间&#xff0c;把之前没整理完的前端动态背景登录页面给整理一下&#xff01;这是之前的连接前端H5动态背景登录页面&#xff08;上&#xff09;&#xff0c;这主要是两个登陆页面&#xff0c;一个彩色气泡&#xff0c;一个动态云朵&#xff0c;感兴趣的可以点…

关爱通丨从AIGC到硅基人同事:人工智能迭代重塑HR管理策略

2024年&#xff0c;一股创新的浪潮悄无声息地席卷了全球&#xff0c;推动了人工智能领域的重大突破。Sora视频模型的惊艳发布&#xff0c;成为了这一创新浪潮的标志性事件。 Sora这个名字源自日语中的“空”&#xff08;そら sora&#xff09;&#xff0c;象征着天空的无限广阔…

机器学习作业3____决策树(CART算法)

目录 一、简介 二、具体步骤 样例&#xff1a; 三、代码 四、结果 五、问题与解决 一、简介 CART&#xff08;Classification and Regression Trees&#xff09;是一种常用的决策树算法&#xff0c;可用于分类和回归任务。这个算法由Breiman等人于1984年提出&#xff0c;它…

sorensen索伦森电源维修XRF系列程控电源XRF600-4

AMETEK直流电源产品有两种类型&#xff1a;固定量程类型和自动量程类型。 固定量程电源是经济型的&#xff0c;输出范围为传统的矩形范围。 自动量程电源&#xff0c;在满输出功率的基础上&#xff0c;扩展了电流和电压的输出范围&#xff0c;使其能够满足更广泛的测试需求&am…

自由场、半自由场、扩散场

按声场性质可以将声场分为三类&#xff1a;自由声场、半自由声场、扩散声场 分别对应着全消声室&#xff0c;半消声室&#xff0c;混响室 自由声场&#xff1a; 声源在均匀、各向同性媒介中传播时&#xff0c;不计边界影响的声场&#xff0c;此时声场中只有直达声没有反射声。…