发表于 2024-8-5 19:58:39

C++ 基础入门篇

定名空间

   定义:定名空间必要用到namespace关键字,其后跟着定名空间的名字(自定义),再接着就是一对花括号,花括号里的内容可以是定义的变量,函数或者结构体
//对命名空间的定义
namespace fun
{
        int a = 1;
        int add(int left,int right)
        {
                return left + right;
        }
        struct Node
        {
                int data;
                int* next;
        }
}
int main()
{
        // ...
        return 0;
}
作用: 定名空间只能使用在全局域中,要知道,不同的域可以定义同一个变量,但在同一个域中不能定义同一个变量,防止在定义某个变量时与全局域产生辩论,空间定名在全局域中就起到了隔离的作用,其在全局域中形成一个定名空间域,该域与全局域互不干涉
若不使用定名空间,在编译时,体系就会出现下面的报错:
https://i-blog.csdnimg.cn/direct/49d120279cbc444bb9717e9972128e5b.png#pic_center
产生辩论时,定名空间就起到了作用:
https://i-blog.csdnimg.cn/direct/4c219a4affca4f7c8d1c72611650049e.png#pic_center
可看到,rang成功打印,并未与在全局域中头文件中的rand产生辩论。在访问定名空间的成员时,必要用到" : : " 域作用限定操纵符,在该操纵符前添上自定义的定名空间名,在其后添上所要访问的成员即可。对于全局域中变量的访问,也可以用此操纵符,在该操纵符前的位置不添任何东西即可
定名空间中定义的变量,函数或结构体作用的范围是全局
https://i-blog.csdnimg.cn/direct/2f1ddaa1091a455b8942c708211b4738.png#pic_center
可以看到在全局域中定义的函数,也可使用定名空间中定义的变量


[*]定名空间的嵌套定义
一个定名空间中可以有多个子定名空间:
https://i-blog.csdnimg.cn/direct/90062af5f64945fca9fadec4a823c88f.png#pic_center
编译查找一个变量/声明时,默认只会在局部和全局域查找,所以想要查找定名空间里的变量/声明的话,有三种方式:

[*]指定访问定名空间
namespace fun
{
        int a = 10;
        int add(int x, int y)
        {
                return x + y;
        }
}
int main()
{
        printf("%d\n",fun::a); // 指定访问命名空间中的变量a
        return 0;
}

[*]全部睁开
namespace fun
{
        int a = 22;
        int b = 10;
}
using namespace fun; //将命名空间域全部展开成全局域
int main()
{
        printf("%d\n",a); // 展开之后命名空间中的变量可当成全局域使用
        printf("%d\n",b);
        return 0;
}
全部睁开相当于将定名空间中的成员全部暴露在全局域中,这样的方式一般不适用于多人合作时使用,一般适用于个人做一些训练或简单步伐时

[*]部分睁开
namespace fun
{
        int x = 1;
        int y = 0;
}
unsing fun::x; // 只对命名空间中的x进行展开
int main()
{
        printf("%d\n",x);
        printf("%d\n",fun::y);
        return 0;
}
   

[*]C++标准库都放在一个叫std(stdandar)的定名空间中
[*]当项目工程中多文件中定义了同名的namespace,编译器会自动以为是同一个namespace,不会产生辩论
输入与输出

与C语言相比,C++的输入和输出会更加的灵活,来看下面的代码:
https://i-blog.csdnimg.cn/direct/9bd84a83190b489eaf7685df8ee1f46e.png#pic_center


[*]”iostream“是标准输入,输出流的库,由于C++的标准库都被放在std的定名空间中,所以在访问库时须以访问定名空间的方式,来对库进行访问
[*]std::cin 是istream类的对象,主要是面向窄字符的标准输入流
[*]std::cout 是ostream类的对象,主要是面向窄字符的标准输出流
[*]std::endl 是一个函数,相当于一个换行符加革新缓冲区
[*]<< 是流的插入/输出运算符,>> 是流的提取/输入运算符
与C语言相比,C++的输入和输出不消一个指定格式或者多个格式,在写代码时,更加的方便
int main()
{
        int i = 10;
        char b = 'A';
        std::cout << i << std::endl << b << std::endl; // 不同类型的变量进行同时输出
        return 0;
}
缺省参数

   概念:缺省参数是在声明或定义函数时,为函数设定一个缺省值(默认值),在调用函数时,若没有指定实参,则该函数就默认使用设定好的缺省值;若指定了实参,则使用实参的值
例:
https://i-blog.csdnimg.cn/direct/62ac8ddc434249679ec3ad9b7d35a8f3.png#pic_center
可知,当第一次调用函数时,没有指定实参,a的值默以为缺省值4;当第二次调用函数时,指定了实参44,a的值为指定的实参
分类:


[*]全缺省:函数中有多个参数,每个参数都指定一个缺省值
https://i-blog.csdnimg.cn/direct/601469346ec7405dafc76b5225144453.png#pic_center
调用全缺省参数时,传参只能从左往右传,不可跳跃传参


[*]半缺省:函数中有多个参数,参数中至少有一个以上设定有缺省值
https://i-blog.csdnimg.cn/direct/4e0ac94d9b8c4699be6534eaee9c43bd.png#pic_center
设定缺省参数时,只能从右往左依次设定缺省值,不可跳跃设定
   注:在设定缺省参数时,若函数的定义与声明是分离的,那么只能在函数声明时给定缺省值
函数重载

   概念:C++支持在同一作用域中出现同名的函数,但要求函数的参数范例不同,或者函数的参数个数不同,这样的同名函数就被称作函数重载,函数重载弥补了C语言中出现的功能雷同,但不能定义为同名函数的征象
分类:


[*] 参数范例不同
https://i-blog.csdnimg.cn/direct/e3eca6baf7304ae88ae5718dcb09b49e.png#pic_center
可见,两次都调用了同名的add函数,但实质上这两个函数并不雷同,只是功能上雷同
[*] 参数个数不同
https://i-blog.csdnimg.cn/direct/57e2435116324162882ef6f5c95dad03.png#pic_center


[*]参数顺序不同
https://i-blog.csdnimg.cn/direct/45818c2eea4b4d9db910035f4f222363.png#pic_center
顺序不同,本质上实在也是范例不同
引用和const引用

概念:引用就是给变量取别名
定义:
int main()
{
        int i = 10;
        int& ri = i;
        return 0;
}
从上面的代码来看,ri就是 i 的别名, i 是被引用的变量,而 ri 是引用变量,编译器不会给引用变量另外开辟空间,而是与它所引用的变量公用同一个空间,由此可推出,ri 与 i 共用一个空间,若引用变量改变则被引用变量也会改变,反之,亦如此
https://i-blog.csdnimg.cn/direct/748156d8bcf04b11a82ff3055f39b3c8.png#pic_center
引用的特性:


[*]定义引用变量时必须初始化
[*]一个变量可以有多个引用
[*]一个引用变量一旦引用了一个变量,就不可再引用其他变量了(C++的引用不能改变指向)
https://i-blog.csdnimg.cn/direct/bdaf3f687d3545b4930757446cde8b3c.png#pic_center
从上面的代码来看,将e赋值给了b,但是b的地址也不会改变,b已经有了引用变量a,便不会再引用其他变量
引用的使用方式:

[*]作参数
https://i-blog.csdnimg.cn/direct/6091cc538faf4851834046f114d3a2a0.png#pic_center
我们知道,通常实现两个数交换的函数,实参传的是地址,必要用指针吸收,然后再对指针进行解引用,而上面的代码,传的是值,分别用引用变量来进行吸收,然后进行两个数的交换,体现了改变引用变量就会改变被引用变量这一个特点

[*]指针的引用
typedef struct Node
{
        int data;
        struct Node* next;
}SL,*phead;

void SeqListInit(phead& plist,int x)
                        //这里的引用相当于 phead& plist = list
{
        SL* tmp = (SL*)malloc(sizeof(SL));
        if (tmp == NULL)
        {
                perror("malloc fail!");
                exit(-1);
        }
        tmp->data = x;
        tmp->next = NULL;
        plist = tmp;
}

int main()
{
        phead plist = NULL;//plist用来存放链表头结点的地址
        //对链表进行初始化
        SeqListInit(plist, 4);
        return 0;
}
代码效果:
https://i-blog.csdnimg.cn/direct/a6942df335994ec0b1108b9b7c61cc21.png#pic_center
我们知道,在对链表进行初始化时,想要改变一级指针的指向就必要取一级指针的地址,然后用二级指针来吸收,通过对二级指针的解引用,就可改变一级指针的指向。但是使用C++的引用,就可以代替指针传参,也可以改变一级指针的指向,这样可较好的简化步伐,避免指针肴杂

[*]作返回值
用栈顶元素来举个例子:
https://i-blog.csdnimg.cn/direct/40bef6dc0ca9449cb76bed02b8235bb3.png#pic_center
体系在进行编译时,会有返回值的临时拷贝,并非直接将要返回的对象(st.arr)直接返回,所以在返回值的范例为int时,体系会为返回值开辟一个空间作为临时对象,来存储返回值,然后再返回临时对象(相当于返回的是要返回的对象的临时拷贝),所以在实行++StackTop(st)的操纵时,实在是对临时对象进行++,而临时对象具有常性不能对其进行++的操纵;而如果引用作为返回值,则相当于返回的是 st.arr 的别名,即可以直接对别名进行修改,不会对其进行报错,体系在编译时也不会对其进行拷贝和开辟一个临时空间,
但是并不是任何场景都能用引用返回的,例如 :
https://i-blog.csdnimg.cn/direct/2c4d84f328924bc6b652533c4c1553f6.png#pic_center
调用fun()这个函数,在该函数中创建了临时变量 i ,而当调用结束,函数烧毁时,该临时变量 i 也会被烧毁,而对引用了 i 的别名进行修改,会造成越界访问,所以引用临时变量不可作为返回值
   注:引用和指针是相辅相成的,二者皆不可替换,指针可以改变指向的对象,但引用改变不了,C++使用引用能简化步伐,避免使用复杂的指针
const引用
   概念:被const修饰的变量会受到权限,不可修改,有const的对象必须用const引用
int main()
{
        const int x = 10;
        const int& rx = x; //x受到const的修饰,所以rx也必须用const
        return 0;
}
在使用const的过程中必要留意:不可放大const对象的权限,但可以缩小没有const对象的权限,缩小了之后,被引用的对象可修改,引用对象不可修改


[*]不可放大权限
https://i-blog.csdnimg.cn/direct/a0ecff2c5f644f65b6eda149a112b7b0.png#pic_center
上述代码中的x受到了const的权限,当定义x的别名rx时,由于别名是不开辟空间的,与被引用对象共用同一块空间,x的空间受到限制,那么定义的x的别名rx也应受到限制,不可放大x空间的权限


[*]可以缩小权限
https://i-blog.csdnimg.cn/direct/0cbfcf4f921c426d9eff77c9416e19aa.png#pic_center
可看到,第二条指令被const修饰,缩小了rx的权限,所以rx不可修改,但是x并未受到权限的影响,所以x可修改
对const运用的延伸
int main()
{
        const int x = 10;
        int y = x;
        return 0;
}
上述代码是精确的,不存在权限的放大,const修饰的是x的这块空间,而将x赋给y是一种赋值拷贝,y也不与x共用同一块空间,所以不存在权限的放大
int main()
{
        const int a = 10;
        const int* p1 = &a;
        int* p2 = p1;
        return 0;
}
上述代码是错误的,这属于权限的放大,第二条指令中,const修饰的不是p1本身,修饰的是p1所指向的空间a不可被修改,且a受到了const的修饰,而将p1赋值给p2时,p2也应受到const的限制
int main()
{
        int b = 20;
        const int* p1 = &b;
        const int* p2 = p1;
        return 0;
}
上述代码精确,属于权限的缩小,变量b可读可写,将b的地址赋给p1后,p1又受到了const的权限,所以p2也应受到const的权限
int main()
{
        int c = 30;
        int* const p1 = &c;
        int* p2 = p1;
        return 0;
}
上述代码时精确的,不存在权限的放大,const修饰p1本身,并非其指向的空间c,p2 = p1相当于一个赋值拷贝,不影响p2对空间c的读写
指针和引用的关系

[*]引用不开辟空间,指针必要开辟空间来存储变量的地址
[*]引用必须初始化,而指针可不初始化
[*]引用的指向一旦确定则不再修改,而指针的指向可随时修改
[*]引用了直接访问指向的对象,而指针需解引用才可访问
[*]引用的大小根据所指向的对象的范例决定,指针的大小在32位平台下是4字节,在64位平台下是8字节
[*]引用的安全性较高于指针
注:引用在语法上是不开辟空间的,但在汇编底层中,实在跟指针是一样的,也必要开辟空间:
int main()
{
        int x = 10;
        int& rx = x;
        rx += 1;

        int* px = &x;
        *px += 1;
        return 0;
}
上述代码的汇编层如下:
https://i-blog.csdnimg.cn/direct/e36bfe0c856243d48b750da05d1a2136.png#pic_center
可以看到,底层的汇编指令一模一样,所以引用的底层实现,与指针的实现是一样的
inline(内联函数)

   概念:inline放在返回值的前面,用来修饰函数。编译器会对调用的inline函数进行睁开,睁开之后就不必要再建立函数栈帧,可进步步伐的效率,inline函数的出现实在就是代替C语言中的宏,宏的使用直接在预处理阶段直接睁开,可进步效率,但是宏的坑太多,所以就有了inline的出现
例如:
#include <iostream>
using std::cout;
using std::endl;
inline int add(int x,int y)
{
        int ret = x + y;
        return ret;
}
int main()
{
        int sum = add(1,2);
        cout << sum << endl;
        return 0;
}
不睁开的汇编指令如下:
https://i-blog.csdnimg.cn/direct/9797eb07f1a14701805036b4cc5d1c11.png#pic_center
不睁开时,会有一条call指令,编译器会进入到call指令中,然后跳转到函数中,创建函数栈帧
睁开的汇编指令如下:
https://i-blog.csdnimg.cn/direct/cbfe3d4b843640bca4df41967e4c9b55.png#pic_center
显然睁开后是没有call指令的,直接将实现函数的指令睁开,也不会去建立函数栈帧
注:inline的使用对编译器来说只是一种发起,对函数的睁开与否还是取决于编译器,一般来说,对于内联函数,如果短小的函数,编译器会对其进行睁开,若函数过大,编译器就不会对其进行睁开
在debug版本下,内联函数默认是不睁开的(必要手动设置)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: C++ 基础入门篇