数据结构还是很早之前学的了,当时才刚学过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包含的最大的数,具体原因我之前写过一篇博客说过。

C语言的补码表示和unsigned及signed的转换

所以我把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写线性表的几点感想的更多相关文章

  1. [C++]使用vector描述线性表定义及基本操作

    #ifndef VECTORLIST_H #define VECTORLIST_H #include<iostream> #include"linearlist.h" ...

  2. C++编程练习(1)----“实现简单的线性表的顺序存储结构“

    线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素. 故可以用数组来实现顺序存储结构. 用C++编写的利用数组实现简单的读取.插入和删除功能的线性表. #include< ...

  3. 随机排序std::vector,扑克牌,麻将类尤其合用

    有些需要重新对std::vector对象重新排序,特别是游戏,例如说:扑克牌,麻将,抽奖等,C++标准已经为std::vector写好了随机排序的方式,这里做个笔记: #include <alg ...

  4. JAVA中的数据结构——集合类(线性表:Vector、Stack、LinkedList、set接口;键值对:Hashtable、Map接口<HashMap类、TreeMap类>)

    Java的集合可以分为两种,第一种是以数组为代表的线性表,基类是Collection:第二种是以Hashtable为代表的键值对. ... 线性表,基类是Collection: 数组类: person ...

  5. 已知长度为n的线性表采用顺序结构,写一算法删除该线性表中所有值为item的元素

    /** * @author:(LiberHome) * @date:Created in 2019/2/27 23:34 * @description: * @version:$ */ /*已知长度为 ...

  6. 数据结构(1) 第一天 算法时间复杂度、线性表介绍、动态数组搭建(仿Vector)、单向链表搭建、企业链表思路

    01 数据结构基本概念_大O表示法 无论n是多少都执行三个具体步骤 执行了12步 O(12)=>O(1) O(n) log 2 N = log c N / log c N (相当于两个对数进行了 ...

  7. Java数据结构之线性表

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  8. [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)

    循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...

  9. c++转载系列 std::vector模板库用法介绍

    来源:http://blog.csdn.net/phoebin/article/details/3864590 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作 ...

随机推荐

  1. 11g OCM自动打补丁

    1.先替换掉OPatch软件 每个实例都要运行 GRID_HOME和ORACLE_HOME的OPatch目录都去除掉 把OPatch软件p6880880_112000_Linux-x86-64.zip ...

  2. java程序设计基础篇 复习笔记 第三单元

    1 单向if语句 双向if语句 dangling else switch:char,byte,short,int 2 javax.swing.JOptionPane.showConfirmDialog ...

  3. 《Effective C++》第5章 实现-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  4. redis的Hash类型以及其操作

    hashes类型 hashes类型及操作Redis hash是一个string类型的field和value的映射表.它的添加.删除操作都是0(1)(平均).hash特别适合用于存储对象.相较于将对象的 ...

  5. java反射抄的例子

    package com.reflect; import java.lang.reflect.Field; import java.lang.reflect.Modifier; /* * 反射的概念 * ...

  6. PostgreSQL时间格式及相关函数实践

    在创建表的时候,有客户需要将时间转为字符串,而且要求了具体的格式,如:20181115101010001.方便记录数据的更新时间,貌似是给Mysql使用,当时就很蛋疼,时间格式存储子啊数据库中就是va ...

  7. 如何实现PLC与THINGWORX工业物联网平台对接

    物联网(Internet of Things),简称 IoT,对于制造商来说,是行业乃至世界范围内的一股变革浪潮.在我们设计和制造的产品中,将会不断嵌入各种软件.传感器和启用 IP 的连接功能.IDC ...

  8. 将sass快速引入到移动端项目中加速开发

    本文以上图为例子: 首先在根目录创建一个sass文件,在sass文件中分别创建4个文件夹bsae,pages,libs,style; base下存放:样式重置_normalize.scss; 自己定义 ...

  9. ARM寄存器总结:

    ARM有16个32位的寄存器(r0到r15). r15充当程序寄存器PC,r14(link register)存储子程序的返回地址,r13存储的是堆栈地址. ARM有一个当前程序状态寄存器:CPSR. ...

  10. DataFrame数据批量做线性回归

    我们通常用pandas读取csv文件为DataFrame数据格式,如下图,是部分县2001年到2009年的某种作物的产量数据.我们希望求得9年的增长趋势,即求一个一元线性回归模型的斜率,这个时候便可以 ...