• 【C++】入门篇-关键字&&命名空间&&输入输出&&缺省参数


    1.C++关键字

    C++总计63个关键字,C语言32个关键字

    ps:下面我们只是看一下C++有多少关键字,不对关键字进行具体的讲解。后面我们学到以后再细讲。

    asmdoifreturntrycontinue
    autodoubleinlineshorttypedeffor
    booldynamic_castintsignedtypeidpublic
    breakelselongsizeoftypenamethrow
    caseenummutablestaticunionwchar_t
    catchexplicitnamespacestatic_castunsigneddefault
    charexportnewstructusingfriend
    classexternoperatorswitchvirtualregister
    constfalseprivatetemplatevoidtrue
    const_castfloatprotectedthisvolatilewhile
    deletegotoreinterpret_cast

    2.命名空间

    为什么存在

    为了解决命名冲突

    #include
    #include//里面包含rand函数
    int rand = 0;//全局变量rand
    int main()
    {
    	printf("rand = %d\n", rand);//编译器不知道打印的是函数的地址(函数名 == 函数的地址)还是全局变量rand的值
      printf("%d\n",rand());//这样没问题,这样相当于是调用rnad函数
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    image-20220407150621806


    但是写成这样没问题

    #include
    #include
    int main()
    {
    int rand = 0;//此时的rand变量为局部变量,局部优先,
     printf("rand = %d\n", rand);//0   局部优先,打印的是局部变量rand的值
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    若rand为全局变量则有问题了,因为rand函数和rand变量都是全局变量,编译器不知道哪个是你要打印的是哪个


    但是若rand为局部变量就没有问题,全局变量和局部变量可以同名,使用时原则为:局部优先(先使用局部变量

    编译器寻找变量的规则是:先在该作用域中寻找该局部变量,找不到再去全局变量中找,如果还是找不到,就会报错

    在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。


    • 使用命名空间后
    #include
    #include
    namespace M_Space//定义一个叫M_Space的命名空间-域
    {
    	int rand = 0;
    }
    int a = 10;
    int main()
    {
    	printf("rand = %d\n", rand);
    	// :: 域作用限定符
    	printf("命名空间的rand = %d\n", M_Space::rand);//表示rand再M_Space这个域中寻找
    	M_Space::rand = 10;
    	printf("修改值后:命名空间的rand = %d\n", M_Space::rand);
    
    	printf("%d\n" ,  ::a);//10
        //若域作用限定符的坐标是空白,则说明再全局域中寻找
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    image-20220910231910001


    命名空间的定义

    命名空间是全局的,命名空间里面的成员也是全局的变量

    定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

    • 例子
    namespace MS  //MS是命名空间的名字 - 域
    {
        int a = 0;//a是全局变量,放在静态区,是MS命名空间的成员,
    }
    
    • 1
    • 2
    • 3
    • 4

    域中的成员变量是不能在域中赋值的!只能初始化时候赋初始值


    命名空间中的内容,既可以定义变量,也可以定义函数,也可以创建类型(结构体,联合体…)

    namespace M_Space
    {
    	int a = 0;
    	int Add(int x, int y)
    	{
    		return x +y ;
    	}
    	
    	 struct Student
    	{
    		 int age;
    		 char sex[7];
    	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 命名空间中的结构体使用时的注意事项
    namespace M_Space
    {
    	 struct Student
    	{
    		 int age;
    		 char sex[7];
    	};
    }
    
    M_Space::struct Student stu;//err
    
    struct M_Space::Student stu;//写法1
    
    M_Space::Student stu;//写法2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    写法1-> 域要加载结构体名字前,不能放在struct前

    写法2-》也可以省略struct不写


    • 命名空间内部的变量可以定义时初始化,但是不可以再次在命名空间内再次赋值,要再次赋值要在其它函数内赋值
    namespace M_Space
    {
    	int a = 0;//定义时初始化
    	int b;//只定义不初始化
    	
    	a = 10;//err
    	b = 5;//err
    }
    M_Space::a = 10;//err  在外部赋值也不可以,要在函数内部赋值
    void test()
    {
        M_Space :: a = 10;//可以
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    image-20220910231857487

    原因分析:

    命名空间内创建的是全局变量,全局变量要在函数内部赋值,初始化时只能赋初始值

    int a = 10;
    a = 20;//err
    int main()
    {
    	a = 10;//OK
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.命名空间可以嵌套

    namespace N1
    {
    	int a = 2;
    	namespace N2
    	{
    		int b = 3;
    	}
    }
    int main()
    {
    	N1::a = 2;
    	N1::N2::b = 1;
        //同样也是使用::域作用限定符进行逐层访问
    	printf("a = %d b = %d\n", N1::a, N1::N2::b);// 2 1 
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。

    namespace N1
    {
    	int a = 0;
    	int b = 2;
    }
    namespace N1
    {
    	int a = 1;
    }
    int main()
    {
    	printf("a  = %d b = %d\n", N1::a, N1::b);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    image-20220910231839352

    相同名称的命名空间,最后会合成同一个命名空间中,所以相同名称的命名空间里面的成员名字不能相同,否则会报错


    命名空间不影响变量的属性,它还是全局变量。只是影响了编译器找该变量的规则

    命名空间里面可以只放声明(函数声明)


    命名空间的使用

    方法1:加命名空间名称及作用域限定符 ::

    命名空间名称 :: 成员名;

    namespace M1
    {
    	int a = 10;
    }
    int main()
    {
    	printf("before:M1::a = %d\n", M1::a);//10
    	M1::a = 20;
    	printf("after:M1::a = %d\n", M1::a);//20
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    优缺点:

    • 优点:不会造成命名污染
    • 缺点:使用麻烦

    方法2:使用using将命名空间中成员引入

    using 命名空间名称 :: 要展开的成员;

    namespace M1
    {
    	int a = 10;
    	int b = 20;
    }
    //单独展开M1中的a变量,其它不展开
    using  M1::a;
    
    int main()
    {
    	printf("a = %d\n", a);//10
    	printf("b = %d\n", b);//b未被引入,编译器找不到,会报错
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    想要程序没问题:把b也展开

    using  M1::a;
    using  M1::b;
    
    • 1
    • 2

    方法3:使用using namespace命名空间名称引入

    using namespace 命名空间名称 ;

    这种写法是直接把整个命名空间展开,使用方便,但是命名空间的隔离作用就失效了

    namespace M1
    {
    	int a = 10;
    	int b = 20;
    }
    //把M1这个命名空间展开-展开到全局
    using namespace M1;
    int main()
    {
    	printf("a = %d\n", a);//10
    	printf("b = %d\n", b);//20
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    namespace N1
    {
    	int a = 2;
    	namespace N2
    	{
    		int a = 3;
    	}
    }
    
    using namespace N1;
    int a = 0;
    int main()
    {
    	//printf("a = %d ", a);//err,未知要打印的是N1的成员变量a还是外部的全局变量a
        printf("a = %d ", N1::a);//这样使用了域限定符就可以
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    image-20220910231820323

    命名空间N1展开之后,N1里面的全局变量a和外部的全局变量a重名了。

    N1失去了隔离作用


    优缺点:

    • 优点: 使用成员方便
    • 缺点:由于是展开到全局,如果全局也有相同名字变量或函数名等,会造成命名污染,编译器报错

    3.C++的输入输出

    1.使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含< iostream >头文件以及std标准命名空
    间。
    注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件
    即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文 件不带.h;旧编译器(vc 6.0)中还支持格式,后续编译器已不支持,因此推荐使用

    推荐使用的版本

    #include//input ouput stream  输入输入流 C++输入输出头文件
    using namespace std;//C++库的实现定义在一个叫std的命名空间中
    //这样写 ==>把std这个命名空间的内容展开到全局
    
    • 1
    • 2
    • 3

    老版本

    #include // VC6.0 -> 比较老版本的库,没有命名空间的
    
    • 1

    2.使用C++输入输出更方便,不需增加数据格式控制,比如:整形–%d,字符–%c


    c语言中使用scanf 和 printf进行输入输出,而C++也有输入输出,那就是cin 和 cout,其中cin是输入,搭配>>使用;cout是输出,搭配<<使用.


    输出 cout

    搭配 << 流插入运算符

    #include
    //std命名空间的内容全局展开
    using namespace std;
    int main()
    {
    	cout << "Hello world\n" ;
    	cout << "Hello world" << endl;//endl ->相当于\n
    	cout << "Hello" << " " << "world" << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    #include
    //只展开std命名空间里面的cout和endl成员
    using std::cout;
    using std::endl;
    int main()
    {
    	int a = 0;
    	double d = 3.14;
        //自动识别变量的类型
    	cout << "a  = "  << a  << " d = " << d<< endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20220910231814312


    cout打印的默认就是你写的,不会把小数后面的也打印出来

    int main()
    {
    	double d = 3.14;
    	cout << "d = " << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image-20220910231808574


    输入 cin

    搭配 >> 流提取运算符

    cin也不可读取空格,会自动忽略 和scanf类似

    #include
    //std命名空间的内容展开到全局
    using namespace std;
    int main()
    {
    	int a = 0;
    	double b = 0;
        //自动识别类型
    	cin >> a;
    	cin >> b;
    	printf("a = %d b = %.2lf\n", a, b);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    image-20220910231802263


    #include
    //只展开std命名空间里面的cin成员
    using std::cin;
    int main()
    {
    	int a = 0;
    	double b = 0;
    	cin >> a;
    	cin >> b;
    	printf("a = %d b = %lf\n", a, b);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.缺省参数

    概念

    缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。


    缺省参数的例子

    void Test(int a = 0)
    {
        cout<<"a = "<< a <<endl;
    }
    int main()
    {
        Test();//没有传参时,使用参数的默认值
        Test(1);//传参时,使用指定的实参
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    image-20220910231755901


    全缺省参数

    所以参数都给了缺省值

    void func(int x = 0, int y = 1)
    {
    	cout << "x = " << x << endl;
    	cout << "y = " << y << endl;
    	cout << endl;
    }
    
    int main()
    {
    	func();
    	func(3);
    	func(3, 4);
        //func( ,4)//只给y赋值,x取默认值,err
        //不能在调用的时候指定传给谁
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    image-20220910231742738


    半缺省参数

    缺省部分参数,并且默认值必须从右往左依次给出

    void func(int x, int y = 0)
    {
    	cout << "x = " << x << endl;
    	cout << "y = " << y << endl;
    	cout << endl;
    }
    int main()
    {
    	func(1);
    	func(1,2);
    	//func();//err
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20220910231736087


    半缺省参数必须从右往左依次来给出,不能间隔着给

    即:必须从右往左缺省,必须连续的缺省,不能跳着缺省

    void func(int x = 0,int y,int z = 1)  //err
    {}
    void func(int x,int y = 0,int z)  //err
    {}
    void func(int x,int y ,int z = 0) //OK
    {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    缺省参数不能在函数声明和定义中同时出现

    //func.cpp中
    void func(int x, int y = 0)
    {}
    
    //func.h中
    void func(int x, int y = 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ->报错

    这里是引用

    image-20220910231729973

    原因:

    如果声明与定义函数的位置同时出现缺省参数,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。

    如:
      //func.cpp中
    void func(int x, int y = 0)
    {}
    
    //func.h中
    void func(int x, int y = 2);  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    解决办法:要么在声明中写缺省参数,要么在定义中写缺省参数。推荐写在:声明,因为查看代码的时候一般先看它的声明

    //func.cpp中
    void func(int x, int y)
    {
        cout << "x = " << x << endl;
    	cout << "y = " << y << endl;
    	cout << endl;
    }
    
    //func.h中-写在声明里面
    void func(int x, int y = 2);  
    
    int main()
    {
        func(1);
        func(3,4);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    image-20220910231721129



    缺省值必须是常量或者全局变量

    //缺省值为全局变量
    int c = 0;
    void func(int x,int y = c)
    {}
    
    //缺省值为常量
    void func(int x,int y = 1)
    {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    • 总结

    1.半缺省参数必须从右往左依次来给出,不能间隔着给

    2.缺省参数不能在函数声明和定义中同时出现

    3.缺省值必须是常量或者全局变量

    4.C语言不支持(编译器不支持)


    使用缺省参数的好处(例子)
    struct Stack
    {
        int* a ;
        int capacity;
        int size;
    }
    //使用缺省参数
    void StackInit(struct Stack* ps,int capacity = 4)
    {
        ps- > a = (int*)malloc(sizeof(int)*capacity);
        ps -> size = 0;
        ps -> capacity = capacity;
    }
    
    int main()
    {
        struct Stack st;
        //StackInit(&st);//不知道栈最多存多少数据,就用缺省参数初始化
        StackInit(&st,100);//知道栈最多存100个数据,用显示传值,这样可以减少增容次数,提高效率
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    增容是有代价的:realloc ():若后面空间不够,要重新开辟空间,把原空间数据拷贝过去,然后释放原空间

    缺省参数函数相比于普通的函数调用时更灵活,比如在栈的初始化时可以通过传入指定的参数开辟对应大小的内存空间,如果不指定参数则开辟默认大小

  • 相关阅读:
    快速创建Jenkins Job
    我的IC秋招小结
    网络安全-黑客技术-小白学习
    Java线程与锁-3
    基于JAVA作品测评网站计算机毕业设计源码+系统+数据库+lw文档+部署
    【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
    RefConv: 重参数化的重新聚焦卷积(论文翻译)
    如何使用MybatisPlus进行数据分页显示
    @RequestParam注解的正确使用方式
    华为云云耀云服务器L实例评测|在Docker环境下部署PrestaShop电子商务系统
  • 原文地址:https://blog.csdn.net/chuxinchangcun/article/details/126800802