千家信息网

C++中指针,引用和STL的示例分析

发表于:2025-01-21 作者:千家信息网编辑
千家信息网最后更新 2025年01月21日,这篇文章主要介绍C++中指针,引用和STL的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!对象的定义:对象是指一块能存储数据并具有某种类型的内存空间一个对象a,它有值和
千家信息网最后更新 2025年01月21日C++中指针,引用和STL的示例分析

这篇文章主要介绍C++中指针,引用和STL的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

    对象的定义:对象是指一块能存储数据并具有某种类型的内存空间

    一个对象a,它有值和地址;运行程序时,计算机会为该对象分配存储空间,来存储该对象的值,通过该对象的地址,来访问存储空间中的值。

    指针、引用

    指针

    类型名 * 指针变量名;

    每个变量都被存放在从某个内存地址(以字节为单位)开始的若干个字节中;"指针",也称作"指针变量",大小为4个字节(或8个字节)的变量,其内容代表一个内存地址;通过指针,能够对该指针指向的内存区域进行读写。

    int * p;    //p是一个指针,变量p的类型是int *
    T * p;    //T可以是任何类型的名字,比如int, doublep     的类型:    T**p    的类型:    T通过表达式 *p,可以读写从地址p开始的sizeof(T)个字节*p    等价于存放在地址p处的一个T类型的变量*     间接引用运算符sizeof(T*)    4字节(64位计算机上可能8字节)
    char ch2 = 'A'char *pc = &ch2;    //使得pc指向变量ch2&: 取地址运算符&x: 变量x的地址(即指向x的指针),对于类型为T的变量x,&x表示变量x的地址(即指向x的指针)&x的类型是T*

    指针的作用

    使用指针,就有自由访问内存空间的手段

    不需要通过变量,就能对内存直接进行操作。通过指针,程序能访问的内存区域就不仅限于变量所占据的数据区域。

    指针的相互赋值

    不同类型的指针,如果不经过强制类型转换,不能直接互相赋值。

    指针的运算

    • 两个同类型的指针变量,可以比较大小(比较的是地址空间的大小)

    • 两个同类型的指针变量,可以相减(相减值为地址空间差值除以sizeof(T))

    • 指针变量加减一个整数的结果是指针

    p: T*类型的指针n: 整数类型的变量或常量p + n: T*类型的指针,指向地址(地址 p + n * sizeof(T))n + p, p - n, *(p + n), *(p - n) 分别为地址和地址指向的值eq:int a = 10;int b = 15;int * p = &a;    //0x61fe04int * q = &b;    //0x61fe00int * ans = p + 2;    //0x61fe0cint k = *(p - 1);    //15
    • 指针变量可以自增、自减 (p++, ++p, p--, --p)即p指向的地址n + sizeof(T)或者n - sizeof(T)

    • 指针可以用下标运算符"[]"进行运算

    p是一个T*类型的指针n是整数类型的变量或常量p[n]等价于*(p + n)

    空指针

    地址0不能访问。指向地址0的指针就是空指针

    可以用"NULL"关键字对任何类型的指针进行赋值。NULL实际上就是整数0,值为NULL的指针就是空指针

    int *pn = NULL;char *pc = NULL;int *p2 = 0;

    指针作为函数参数(形参是实参的一个拷贝)

    指针和数组

    数组的名字是一个指针常量(指向数组的起始地址)

    T a[N];a的类型是T*可以用a给一个T*类型的指针赋值a是编译时其值就确定了的常量,不能够对a进行赋值

    作为函数形参时,T *p和 T p[]等价

    void Func(int *p){ cout << sizeof(p); }void Func(int p[]){ cout << sizeof(p); }

    引用

    类型名 & 引用名 = 某变量名;(定义了一个引用,将其初始化为引用某个变量)

    int n = 4;int & r = n; //r引用了n, r的类型是int &v

    某个变量的引用,等价于这个变量,相当于该变量的一个别名

    • 定义引用时一定要将其初始化成引用某个变量

    • 初始化后,它就一直引用该变量,不会再引用别的变量

    • 引用只能引用变量,不能引用常量和表达式

    引用作为函数的返回值

    int n = 4;int & SetValue() {    return n;}int main(){    SetValue() = 40;    cout << n;    //输出是40    return 0;}

    常引用

    定义引用时,前面加const关键字,即为"常引用"

    int n;const int & r = n;    //r的类型是const int &
    不能通过常引用去修改其引用的内容:int n = 100;const int & r = n;r = 200;    //编译错误n = 300;    //ok

    常引用和非常引用的转换

    const T &和 T &是不同的类型,T &类型的引用或T类型的变量可以用来初始化const T &类型的引用;const T类型的常变量和const T &类型的引用则不能用来初始化T &类型的引用。

    STL

    STL中六大组件

    容器(Container,一种数据结构(包含一组元素或元素集合的对象),基本容器:向量(vector), 双端队列(deque), 列表(list), 集合(set), 多重集合(multiset), 映射(map), 多重映射(multimap)。

    序列式容器(Sequence containers),其中每个元素均有固定位置--取决于插入时机和地点,和元素值无关(vector, deque, list)

    关联式容器(Associative containers),元素位置取决于特定的排序准则以及元素值,和插入次序无关(set, multiset, map, multimap)

    迭代器(Iterator)

    迭代器Iterator,用来在一个对象集群(collection of objects)的元素上进行遍历。这个对象集群或许是一个容器,或许是容器的一部分。迭代器的主要好处是,为所有容器提供了一组很小的公共接口。迭代器以++进行累进,以*进行提领,因而类似于指针,可以将其视为一种smart pointer。

    例如++操作可以遍历至集群内的下一个元素。至于如何完成,取决于容器内部的数据组织形式。

    每种容器都提供自己的迭代器,而这些迭代器能够了解容器内部的数据结构

    算法(Algorithm)

    用来处理群集内的元素。它们可以出于不同的目的而搜寻、排序、修改、使用那些元素。通过迭代器的协助,我们可以只需编写一次算法,就可以将它应用于任意容器,这是因为所有的容器迭代器都提供一致的接口。

    仿函数(Functor)

    适配器(Adaptor)

    提供三种顺序容器适配器:queue(FIFO队列),priority_queue(优先级队列),stack(栈)。

    适配器对容器进行包装,使其表现出另外一种行为。倘若要使用适配器,需要加入头文件

    分配器(Allocator)

    常用容器用法介绍

    vector

    一个数组必须有固定的长度,在开数组的时候,此长度就被静态地确定下来。但vector却是数组的"加强版",vector理解为一个"变长数组"

    事实上,vector的实现方式是基于倍增思想的:假如vector的实际长度为n,m为vector当前的最大长度,那么在加入一个元素的时候,先看一下,假如当前的n=m,则再动态申请一个2m大小的内存。反之,在删除的时候,如果n≥m/2,则再释放一半的内存。

    #includevectorvec;vector >vec_pair;struct node{ ... };vectorvec_node;

    vec.begin(), vec.end() 返回vector的首尾迭代器

    vec.front(), vec.back() 返回vector的首尾元素

    vec.push_back() 从vector末尾加入一个元素

    vec.size() 返回vector当前的长度(大小)

    vec.pop_back() 从vector末尾删除一个元素

    vec.empty() 返回vector是否为空,1为空,0不为空

    vec.clear() 清空vector

    vector容器是支持随机访问的,可以像数组一样用[]取值。

    vectorvec;vec.push_back(5);vec.push_back(2);cout << vec.back() << endl;for(vector::iterator iter = vec.begin(); iter != vec.end(); iter++){    cout << *iter << endl;}

    vector修改值

    • 有迭代器,使用迭代器修改 auto iter = v.begin(), *iter = 1

    • 使用索引进行修改 v[0] = 1

    deque(双端队列)

    #include<deque>deque<int>q

    q.begin(), q.end() 返回deque的首尾迭代器

    q.front(), q.back() 返回deque的首尾元素

    q.push_back() 从队尾入队一个元素

    q.push_front() 从队头入队一个元素

    q.pop_back() 从队尾出队一个元素

    q.pop_front() 从队头出队一个元素

    q.size()z 队列中元素个数

    q.clear() 清空队列

    deque支持随机访问,可以像数组下标一样取出其中的一个元素。即q[i]

    deque容器可以被应用到SPFA算法的SLF优化:SPFA算法的优化方式

    set

    set满足互异性,set集合中的元素是默认升序的(set容器自动有序和快速添加、删除的性质是由其内部实现:红黑树(平衡树的一种))

    #includesetsset >s;

    s.empty() 返回集合是否为空,是为1,否为0

    s.size() 返回当前集合的元素个数

    s.clear() 清空当前集合

    s.begin(), s.end() 返回集合的首尾迭代器(迭代器是一种指针。这里需要注意的是,由于计算机区间"前闭后开"的结构,begin()函数返回的指针指向的的确是集合的第一个元素。但end()返回的指针却指向了集合最后一个元素后面一个元素。)

    s.insert(k) 集合中加入元素k

    s.erase(k) 集合中删除元素k

    s.find(k) 返回集合中指向元素k的迭代器。如果不存在这个元素,就返回s.end(),这个性质可以用来判断集合中有没有这个元素。

    s.lower_bound() 返回集合中第一个大于等于关键字的元素

    s.upper_bound() 返回集合中第一个严格大于关键字的元素

    multiset(有序多重集合)

    s.erase(k)

    erase(k)函数在set容器中表示删除集合中元素k。但在multiset容器中表示删除所有等于k的元素。

    倘若只删除这些元素中的一个元素

    if((it = s.find(a)) != s.end())    s.erase(it);if中的条件语句表示定义了一个指向一个a元素的迭代器,如果这个迭代器不等于s.end(),就说明这个元素的确存在,就可以直接删除这个迭代器指向的元素。

    s.count(k) count(k)函数返回集合中元素k的个数,为multiset所独有。

    map

    可以根据键值快速地找到这个映射出的数据, map容器的内部实现是一棵红黑树

    #includemap mp;建立一个从整型变量到字符型变量的映射
    mapmp;//插入mp[1] = 'a';mp.insert(map::value_type(2, 'b'));mp.insert(pair(3, 'c'));mp.insert(make_pair(4, 'd'));//查找mp[3] = 't';    //修改键值对中的值map::iterator iter;iter = mp.find(3);iter->second = 'y';cout << iter->second << endl;//删除mp.erase(2);    //删除键值对//遍历for(map::iterator iter = mp.begin(); iter != mp.end(); iter++){    cout << iter->first << endl;    cout << iter->second << endl;}

    mp.begin(), mp.end() 返回首尾迭代器

    mp.clear() 清空函数操作

    mp.size() 返回容器大小

    queue(FIFO)

    #includequeueq;queue >q;#includequeueq;queue >q;

    q.front(), q.back() 返回queue的首尾元素

    q.push() 从queue末尾加入一个元素

    q.size() 返回queue当前的长度(大小)

    q.pop() 从queue队首删除一个元素

    q.empty() 返回queue是否为空,1为空,0不为空

    priority_queue

    优先队列在队列的基础上,将其中的元素加以排序。其内部实现是一个二叉堆。优先队列即为将堆模板化,将所有入队的元素排成具有单调性的一队,方便我们调用。

    大根堆声明就是将大的元素放在堆顶的堆。优先队列默认实现的就是大根堆。

    小根堆声明就是将小的元素放在堆顶的堆。

    #includepriority_queueq;        //大根堆priority_queueq;priority_queue >q;    priority_queue, less >q;    //大根堆priority_queue, greater >q;    //小根堆

    q.top() 返回priority_queue的首元素

    q.push() 向priority_queue中加入一个元素

    q.size() 返回priority_queue当前的长度(大小)

    q.pop() 从priority_queue末尾删除一个元素

    q.empty() 返回priority_queue是否为空,1为空,0不为空

    stack(栈)

    #include<stack>stack<int> st;stack<pair<int, int> > st;

    st.top() 返回stack的栈顶元素

    st.push() 从stack栈顶加入一个元素

    st.size() 返回stack当前的长度(大小)

    st.pop() 从stack栈顶弹出一个元素

    st.empty() 返回stack是否为空,1为空,0不为空

    string(字符串操作)

    其实string容器就是一个字符串

    操作string字符阵列
    声明字符串string schar s[100]
    取得第i个字符s[i]s[i]
    字符串长度s.length(), s.size()strlen(s) 不计\0
    读取一行getline(cin, s)gets(s)
    设成某字符串s = "TCGS"strcpy(s, "TCGS")
    字符串相加s = s + "TCGS"strcat(s, "TCGS")
    字符串比较s == "TCGS"strcmp(s, "TCGS")

    重载运算符

    C++语言中已经给出的运算符(算数运算符和逻辑运算符)只是针对C++语言中已经给定的数据类型进行运算。倘若我们想要对我们自定义数据类型进行运算的话,则需要重载运算符,我们可以把重载运算符理解为对已有的运算符的一种重新定义。

    重载运算符的实现

    语法格式如下<返回类型> operator <运算符符号>(<参数>){    <定义>;}
    //定义结构体struct node{    int id;    double x, y;}; //重载运算符"<"bool operator < (const node &a, const node &b)  {    if(a.x != b.x)        return a.x < b.x;    else        return a.y < b.y;}

    以上是"C++中指针,引用和STL的示例分析"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

    0