2.2 Vector<T> 动态数组(模板语法)

这篇具有很好参考价值的文章主要介绍了2.2 Vector<T> 动态数组(模板语法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++数据结构与算法 目录

本文前驱课程

1 C++自学精简教程 目录(必读)

2 动态数组 Vector(难度1)

其中,2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。

本文目标

1 学会写基本的C++类模板语法;

2 为以后熟练使用 STL 打下基础;

3 为更进一步的阅读和掌握更多的C++库打下基础;

模板语法的学习最恰当的方式就是和非模板代码对比学习。

本文的内容只是在 2 动态数组 Vector(难度1)的基础上,把代码改造为模板语法。

除此之外,不添加任何内容。

模板语法介绍

当类的成员变量是不确定的类型的时候,我们使用模板类( template class)来实现这样的类。

模板类的定义如下:

    template<typename T>  
    struct Vector{
        T data;//成员变量 data 的类型不确定,写成 T
    };

解释说明:

(1)template 表示后续代码中有类型是不确定的,先用typename T当中的T表示类型;

(2)typename表示T是一个未来才能确定的类型

(3)确定T的类型的方式就是创建一个Vector对象的时候在<>中指定:文章来源地址https://www.toymoban.com/news/detail-690701.html

 Vector<int> arr;  //这条语句表示用int替换代码中的T

非模板语法与模板语法差异对比图

2.2 Vector<T> 动态数组(模板语法),C++数据结构与算法实现,c++,开发语言,算法
模板语法和非模板语法对比1
2.2 Vector<T> 动态数组(模板语法),C++数据结构与算法实现,c++,开发语言,算法
模板语法和非模板语法对比2

代码与注释如下

#include<iostream>
#include <iomanip>
#include <cassert>
using namespace std;

//------下面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------
#include <algorithm>
#include <cstdlib>
#include <iostream> 
#include <vector>
#include <utility>
using namespace std;
struct Record { Record(void* ptr1, size_t count1, const char* location1, int line1, bool is) :ptr(ptr1), count(count1), line(line1), is_array(is) { int i = 0; while ((location[i] = location1[i]) && i < 100) { ++i; } }void* ptr; size_t count; char location[100] = { 0 }; int line; bool is_array = false; bool not_use_right_delete = false; }; bool operator==(const Record& lhs, const Record& rhs) { return lhs.ptr == rhs.ptr; }std::vector<Record> myAllocStatistic; void* newFunctionImpl(std::size_t sz, char const* file, int line, bool is) { void* ptr = std::malloc(sz); myAllocStatistic.push_back({ ptr,sz, file, line , is }); return ptr; }void* operator new(std::size_t sz, char const* file, int line) { return newFunctionImpl(sz, file, line, false); }void* operator new [](std::size_t sz, char const* file, int line)
{ return newFunctionImpl(sz, file, line, true); }void operator delete(void* ptr) noexcept { Record item{ ptr, 0, "", 0, false }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }void operator delete[](void* ptr) noexcept {Record item{ ptr, 0, "", 0, true }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (!itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); }}
#define new new(__FILE__, __LINE__)
struct MyStruct { void ReportMemoryLeak() { std::cout << "Memory leak report: " << std::endl; bool leak = false; for (auto& i : myAllocStatistic) { if (i.count != 0) { leak = true; std::cout << "leak count " << i.count << " Byte" << ", file " << i.location << ", line " << i.line; if (i.not_use_right_delete) { cout << ", not use right delete. "; }	cout << std::endl; } }if (!leak) { cout << "No memory leak." << endl; } }~MyStruct() { ReportMemoryLeak(); } }; static MyStruct my; void check_do(bool b, int line = __LINE__) { if (b) { cout << "line:" << line << " Pass" << endl; } else { cout << "line:" << line << " Ohh! not passed!!!!!!!!!!!!!!!!!!!!!!!!!!!" << " " << endl; exit(0); } }
#define check(msg)  check_do(msg, __LINE__);
//------上面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------

//注意:禁止修改Vector的定义,包括禁止给Vector添加成员变量;
//可以添加私有成员函数,如果你认为需要的话

template<typename T>
struct Vector
{
public:
    Vector();
    Vector(int n, T value);
    Vector(const Vector& from);
    Vector(int* begin, int* end);
    ~Vector();
    int size() const;
    //只读元素
    //参考 https://zhuanlan.zhihu.com/p/539451614
    const T& operator[](int n)const { return m_data[n]; }
    //写入元素
    T& operator[](int n) { return m_data[n]; }
    void push_back(T value);
    bool empty() const;// your job 1
    void clear();// your job 2
    Vector& operator = (const Vector& from);// your job 4
private:
    void copy(const Vector& from);// your job 3
private:
    int m_element_cout;
    int m_capacity;
    T* m_data;//定义一个元素类型待定的数组起始元素的指针
    //请忽略下面这个成员变量,这个成员变量不影响你的实现,当它不存在即可。
};

//模板类的成员函数都要以下面的template语法开始,和类声明的地方一样
template<typename T>
Vector<T>::Vector()
{
    m_element_cout = 0;
    m_capacity = 10;
    m_data = new int[m_capacity];
}

template<typename T>
Vector<T>::Vector(int n, T value) :Vector()
{
    for (int i = 0; i < n; i++)
        push_back(value);
}

template<typename T>
Vector<T>::Vector(const Vector& from)
{
    m_element_cout = from.m_element_cout;
    m_capacity = from.m_capacity;
    m_data = new int[m_capacity];
    for (int i = 0; i < m_element_cout; i++)
    {
        m_data[i] = from.m_data[i];
    }
}

template<typename T>
Vector<T>::Vector(int* begin, int* end) :Vector()
{
    for (int* p = begin; p < end; p++)
    {
        push_back(*p);
    }
}

template<typename T>
Vector<T>::~Vector()
{
    delete[] m_data;
}

template<typename T>
int Vector<T>::size() const
{
    return m_element_cout;
}

template<typename T>
void Vector<T>::push_back(T value)
{
    if (m_element_cout < m_capacity)
    {
        m_data[m_element_cout] = value;
        m_element_cout++;
    }
    else
    {
        int* p;
        p = new T[2 * m_capacity];
        for (int j = 0; j < m_element_cout; j++)
        {
            p[j] = m_data[j];
        }
        p[m_element_cout] = value;
        m_element_cout = m_element_cout + 1;
        m_capacity = 2 * m_capacity;
        delete[]m_data;
        m_data = p;
    }
}

//(1) your code for : Vector empty()






//(2) your code for : Vector clear()







//(3) your code for : Vector copy()







//(4) your code for : Vector operator =









void test1(void)
{
    Vector<int> v;//创建一个存放int变量的容器v
    int i;
    check(v.size() == 0);
    for (i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    for (int i = 0; i < 10; i++)
    {
        check(v[i] == i);
    }
    check(v.size() == 10);
}
void test2(void)
{
    int n = 100000;
    Vector<int> v;
    int i;
    check(v.size() == 0);
    for (i = 0; i < n; i++)
    {
        v.push_back(i);
    }
    for (int i = 0; i < n; i++)
    {
        assert(v[i] == i);
    }
    check(v.size() == n);
}
void print(Vector<int>& v, const std::string& msg)
{
    std::cout << "The contents of " << msg.c_str() << " are:";
    for (int i = 0; i != v.size(); ++i)
    {
        std::cout << ' ' << v[i];
    }
    std::cout << '\n';
}
void test3()
{
    Vector<int> a;

    Vector<int> first;                   // empty vector of ints
    check(first.empty() == true && first.size() == 0);
    Vector<int> second(4, 100);                       // four ints with value 100
    check(second.empty() == false);
    check(second.size() == 4);
    Vector<int> fourth(second);                       // a copy of third
    check(fourth.size() == second.size());

    int myints[] = { 16,2,77,29 };
    Vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));
    check(fifth.empty() == false);
    check(fifth[0] == 16);
    check(fifth[3] == 29);
    check(fifth.size() == sizeof(myints) / sizeof(int));
    print(fifth, "fifth");//The contents of fifth are:16 2 77 29 
    fifth.push_back(30);
    check(fifth[4] == 30);
    check(fifth.size() == 5);
    print(fifth, "fifth");//The contents of fifth are:16 2 77 29 30 
    check(fifth.size() == sizeof(myints) / sizeof(int) + 1);
    first = fifth = fifth;
    print(first, "first");//The contents of first are:16 2 77 29 30 
    check(first.empty() == false && first.size() == fifth.size());
    Vector<int> a1(myints, myints + sizeof(myints) / sizeof(int));
    //下面大括号是作用域,用来把代码分开互不干扰,这样就可以创建相同的变量名字了,就不用为了起很多不同的变量名而烦恼了。
    {
        Vector<int> b(a1);
        b.push_back(2);
        check(b[4] == 2);
    }
    {
        Vector<int> c;
        c = a1;
    }
    check(a1.size() == sizeof(myints) / sizeof(int));
    {
        Vector<int> c;
        c = fifth;
        c[0] = 1;
        check(c[0] == 1);
    }
}

int main()
{
    test1();
    test2();
    test3();

    return 0;
}

预期输出:

到了这里,关于2.2 Vector<T> 动态数组(模板语法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C/C++数据结构之动态数组篇

    静态数组 :静态数组在内存中位于栈区,是在编译时就已经在栈上分配了固定大小,程序结束由系统释放。在运行时 不能 改变数组大小。 动态数组 :动态数组是malloc(在c语言中使用malloc函数)或者new(在c++中使用new操作符)出来的,位于内存的堆区,它的大小是在程序运行

    2024年02月16日
    浏览(35)
  • 【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)

    🍃 数据结构是 计算机 存储 、 组织 数据的方式 🎉 线性 结构 线性表(数组、链表、栈、队列、哈希表) 🎉 树形 结构 二叉树 AVL 树 红黑树 B 树 堆 Trie 哈夫曼树 并查集 🎉 图形 结构 邻接矩阵 邻接表 🎁 线性表是具有 n 个 相同类型元素 的有限 序列 (n = 0) a1 是首节点

    2024年02月10日
    浏览(63)
  • 【数据结构与算法】Kadane‘s算法(动态规划、最大子数组和)

    Kadane\\\'s 算法是一种用于解决最大子数组和问题的动态规划算法。这类问题的目标是在给定整数数组中找到一个连续的子数组,使其元素之和最大(数组含有负数)。 算法的核心思想是通过迭代数组的每个元素,维护两个变量来跟踪局部最优解和全局最优解。 以下是Kadane’s算

    2024年03月22日
    浏览(86)
  • 数据结构与算法—二叉树数组表示(ArrayBinTree)、二叉树的链式表示(LinkedBinTree)的基于C++模板代码实现

    1、二叉树的顺序表示:ArrayBinTree.h 二叉树的顺序表示法操作方便,但缺点是容易造成存储空间浪费。 这是一个用数组实现的二叉树类模板。它可以创建一个空树,也可以在指定的位置插入结点并设置结点的值,可以删除子树,并支持逐层遍历。使用该类时,需要提供一个元

    2024年02月06日
    浏览(30)
  • 【JavaSE专栏48】Java集合类ArrayList解析,这个动态数组数据结构你了解吗?

    作者主页 :Designer 小郑 作者简介 :3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向 :Vue、SpringBoot、微信小程序 本文讲解了 Java 中集合类 ArrayList 的语法、使用说明和应用场景,并给出了样例代码。

    2024年02月16日
    浏览(50)
  • 2.2比特币(BTC)中的数据结构

    ​ **普通指针存储的是某个结构体在内存中的地址。 假如P是指向一结构体的指针,那么P里面存放的就是该结构体在内存中的起始位置。 而哈希指针除了要存地址之外,还要保存该结构体的哈希值H()。 好处是:从哈希值这个哈希指针,不仅可以 找到该结构体的位置 ,同时还

    2024年02月05日
    浏览(32)
  • C++数据结构之vector

    vector数组是一个能存放任意数据类型(类,结构体,普通变量类型等)的动态数组,在数据结构中就相当于顺序储存的线性表,寻找元素非常快,但是插入元素的时间却很大(list是一个双向链表,在同一个位置插入大量的数据时速度很快,但是查找的速度就会慢很多) 和普

    2024年02月04日
    浏览(35)
  • 【C++入门】STL容器--vector底层数据结构剖析

    目录  前言  1. vector的使用       vector的构造  vector迭代器  vector空间相关的接口  vector 功能型接口  find  swap  insert  erase 2. vector内部数据结构剖析 reserve  push_back和pop_back size、capacity、empty、operator[ ];  insert和erase resize swap  拷贝构造和赋值重载 构造函数补充  迭代器

    2024年01月25日
    浏览(38)
  • DSt:数据结构的最强学习路线之数据结构知识讲解与刷题平台、刷题集合、问题为导向的十大类刷题算法(数组和字符串、栈和队列、二叉树、堆实现、图、哈希表、排序和搜索、动态规划/回溯法/递归/贪心/分治)总

    Algorithm:【算法进阶之路】之算法面试刷题集合—数据结构知识和算法刷题及其平台、问题为导向的十大类刷题算法(数组和字符串、链表、栈和队列、二叉树、堆、图、哈希表、排序和搜索、回溯算法、枚举/递归/分治/动态规划/贪心算法)总结 目录 相关文章

    2024年02月08日
    浏览(43)
  • C++——数组、多维数组、简单排序、模板类vector

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,正逐渐往全干发展 📃 个人状态: 研发工程师,现效力于中国工业软件事业 🚀 人生格言: 积跬步至千里,积小流成江海 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒

    2024年01月22日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包