模仿std::vector写线性表的几点感想
数据结构还是很早之前学的了,当时才刚学过C语言,实现得都很简单,最近决定重新打牢基础,于是重新开始实现书上的数据结构和算法。
模仿C++ Primer的StrVec以及std::vector,使用模板类+allocater分配内存,遵循“三/五原则”,期间遇到了几个小问题,记录下。
1、unsigned和signed的比较:
在实现insert操作时,写了个私有方法去把数组index处开始的元素向后移动n位。分两种情况处理,一种是容量不够需要重新分配内存,另一种是容量足够,直接向后移动。
前一种分配内存空间后可以直接用uninitialized_copy搬运元素,也可以用Allocater::construct构造元素。而后一种是在原先分配的内存上重新构造元素,因此要注意先更新的位置就不要再使用。
如上图,把index为1开始的元素向后移动1位。如果从前往后移动,第一次就会改动位置2处的元素,但是位置2处的元素需要移动到位置3处,这样就造成了错误。
因此需要从后移动,我之前的代码就是 for (size_t i = count - 1; i >= index; --i)
乍看之下没有问题,但是在index为0的时候就出错了。size_t是unsigned int,假如是为0再自减,会变成unsigned包含的最大的数,具体原因我之前写过一篇博客说过。
所以我把size_t改成了int,代码变成 for (int i = count - 1; i >= index; --i)
但是依旧出错,调试发现:int i = -1; unsigned index = 0; 那么i > index为true。其实编译器已经把问题提出来了:warning c4018 : signed/unsigned mismatch
signed和unsigned进行比较时会都转换成unsigned比较,也就是说虽然i自减成了负数,但是进行比较时会被强制转换为unsigned,这个循环依旧是个死循环。
解决方法:
1、把index强制转换为int,这样就会是signed之间比较;
2、改成for (int i = 0; i < count - index; ++i)然后改变循环体内关于i的部分,这样比较麻烦,而且i不能直接体现出表达的意义。
2、类模板中定义友元函数
如果友元函数的定义在类中则没有什么问题,如果要写在类的外部就有点麻烦。以下面代码为例。
template <typename T>
class SqList; template <typename T>
std::ostream &operator<<(std::ostream &, const SqList<T> &); template <typename T>
class SqList
{
friend std::ostream &operator<< <T>(std::ostream &, const SqList<T> &);
// ...
} template <typename T>
std::ostream &operator<< (std::ostream &os, const SqList<T> &lst)
{
for (auto iter = lst.begin(); iter != lst.end(); ++iter)
os << *iter << ' ';
return os;
}
首先,友元函数需要在类之前进行声明,这点跟普通类的友元函数不同(具体原因需要复习下模板的知识,暂不深究)。而由于友元函数会用到类模板作为参数,所以必须再对类模板进行前置声明。
其次,模板类的友元函数本质上是个函数模板,因此在类模板中进行友元声明时在函数名后用模板参数实例化,否则就会出现经典的外部链接错误error LINK 2019,因为会判断类外部的函数实现(operator<<)并不是对类内的operator<<的实现,所以在调用这个友元方法时编译器找不到定义。
模仿std::vector写线性表的几点感想的更多相关文章
- [C++]使用vector描述线性表定义及基本操作
#ifndef VECTORLIST_H #define VECTORLIST_H #include<iostream> #include"linearlist.h" ...
- C++编程练习(1)----“实现简单的线性表的顺序存储结构“
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素. 故可以用数组来实现顺序存储结构. 用C++编写的利用数组实现简单的读取.插入和删除功能的线性表. #include< ...
- 随机排序std::vector,扑克牌,麻将类尤其合用
有些需要重新对std::vector对象重新排序,特别是游戏,例如说:扑克牌,麻将,抽奖等,C++标准已经为std::vector写好了随机排序的方式,这里做个笔记: #include <alg ...
- JAVA中的数据结构——集合类(线性表:Vector、Stack、LinkedList、set接口;键值对:Hashtable、Map接口<HashMap类、TreeMap类>)
Java的集合可以分为两种,第一种是以数组为代表的线性表,基类是Collection:第二种是以Hashtable为代表的键值对. ... 线性表,基类是Collection: 数组类: person ...
- 已知长度为n的线性表采用顺序结构,写一算法删除该线性表中所有值为item的元素
/** * @author:(LiberHome) * @date:Created in 2019/2/27 23:34 * @description: * @version:$ */ /*已知长度为 ...
- 数据结构(1) 第一天 算法时间复杂度、线性表介绍、动态数组搭建(仿Vector)、单向链表搭建、企业链表思路
01 数据结构基本概念_大O表示法 无论n是多少都执行三个具体步骤 执行了12步 O(12)=>O(1) O(n) log 2 N = log c N / log c N (相当于两个对数进行了 ...
- Java数据结构之线性表
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)
循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...
- c++转载系列 std::vector模板库用法介绍
来源:http://blog.csdn.net/phoebin/article/details/3864590 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作 ...
随机推荐
- SQL 添加字段
制定添加在那个字段后面 ALTER TABLE `szq`.`org_sales_daily` ADD COLUMN `trade_id_onl_count` int(11) NOT NULL DEF ...
- Markdown - 让网络书写变得简单
概述 宗旨 Markdown 的目标是实现「易读易写」. 可读性,无论如何,都是最重要的.一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布,并且看起来不会像是由许多标签或是格式指令所 ...
- Python基本常用算法
什么是算法 就是一个计算的过程,解决问题的方法 用到知识点 递归 调用自身 有结束条件 下次执行相应的复杂度要减少 时间复杂度排序(按效率排序) O(1)<O(logn)<O(n)< ...
- PHP Socket(套接字连接)扩展简介和使用方法
PHP socket扩展是基于流行的BSD sockets,实现了和socket通讯功能的底层接口,它可以和客户端一样当做一个socket服务器. 使用这些函数时请注意,虽然他们中有很多和C函数同名的 ...
- PHP获取随机数的函数rand()和mt_rand()
rand()函数用户获取随机数,具体用法如下: rand()可以设置0个参数或者两个参数,如rand($min,$max),$min表示从XX开始取值,$max表示最大只能为XX 例如: <?p ...
- L161
The robot arm made for gentle undersea explorationA soft robotic arm which will allow underwater sea ...
- jquery过滤特殊字符及js字符串转为数字
//替换特殊字符 $(this).val($(this).val().replace(/[~'!<>@#$%^&*()-+_=:]/g, "")); 方法主要有 ...
- SQL SERVER - set statistics time on的理解
一.set statistics time on的作用 显示分析.编译和执行各语句所需的毫秒数. 二.语法 SET STATISTICS TIME { ON | OFF } 注释 1.当 SET ST ...
- 浅析Symbol
不知道大家有没有留意ES6中的Symbol函数?在此之前,我对Symbol的认识知识这样的: 一.Symbol()和Symbol.for('str') Symbol()是独一无二的,你无法创建两个相 ...
- python3精简笔记(三)——高级特性
Python中 1行代码能实现的功能,决不写5行代码.请始终牢记,代码越少,开发效率越高. 切片 取一个list或tuple的部分元素是非常常见的操作.Python提供了切片(Slice)操作符 L ...