C++入门,一些C++基本概念介绍

文章目录

目录

前言

1.C++关键字

1.1命名空间

1.2命名空间定义

1.3命名空间的使用

2.C++输入&输出

3.缺省参数

3.1缺省参数的概念

3.2缺省参数分类

4.函数重载

4.1函数重载的概念

5.引用

5.1 引用特性

5.2 常引用

5.3引用的使用场景

5.4引用和指针

6.内联函数

6.1内联的特性

7.宏

8.auto关键字(c++11)

8.1 auto的使用细则

9.基于范围的for循环(语法糖)

9.1范围for的语法

9.2范围for的使用条件

10.指针空值--nullptr(c++11)

总结

 


前言

什么是C++:

        C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,需要高度的抽象和建模时,C语言则不合适。C++是基于C语言产生的,它可以进行C语言的过程化程序设计,又可以以抽象数据类型为特点的,基于对象的程序设计,还可以进行面向对象的程序设计。


1.C++关键字

C++总计63个关键字,如下图所示,具体用法可参考后续文章。

1.1命名空间

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

1.2命名空间定义

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

1、正常的命名空间定义

namespace Queue{
    //命名空间中可以定义变量/函数/类型
    int rand = 10;
    int Add(int left, int right)
    {
        return left+right;
    }
    struct Node
    {
        struct Node * next;
        int val;
    }
}



2、命名空间可以嵌套
namespace N1
{
    int a;
    int b;
    int Add(int left, int right)
    {
        return left+right;
    }


    namespace N2
    {
        int c;
        int d;
        int sub(int left ,int right)
        {
            return left -right;
        }
    }
}


3、同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成在同一个命名空间中
    //test.h 
    namespace N1
    {
        ...
    }
    //test.cpp
    namespace N1
    {
        ...
    }
    
test.h和test.cpp中的两个N1会被合并成一个

注意:一个命名空间就定义了一个新的作用域,命名空间中所有的内容都局限于该命名空间中。

1.3命名空间的使用

命名空间使用有三种方式:

  1. 加命名空间名称以及作用域限定符
  2. 使用using将命名空间中的某个成员引入
  3. 使用using namespace 命名空间名称引入  
namespace byte
{
    int a = 0;
    int b = 1;
    int Add(int left,int right)
    {
          return left+right;
    }
    
    ...
}

int main()
{
    printf("%d" ,a);
}


1.加命名空间名称以及作用限定符
int main()
{
    printf("%d" ,byte::a);
}



2.使用using将命名空间某个成员引入
using byte::b;
int main()
{
    printf("%d" ,b);
}


3.使用using namespace 命名空间名称引入
using namespace N;
int main()
{
  
    printf("%d" ,a);
}


2.C++输入&输出

#include<iostream>
using namespace std;

int main()
{
    cout<<"hello world!"<<endl;
}

说明:

1.使用cout标准输出对象(控制台)和cin标准输入对象时,比如包含<iostream>头文件,以及按命名空间使用方法使用std;

2.<<是流插入运算符; >>是流提取运算符

3.cout和cin是全局的流对象,endl是特殊的c++符号,表示换行输出,都包含在iostream头文件中

4.使用c++输入和输出更方便,c语言中使用printf和scanf需要手动控制格式,c++可以直接自动识别变量类型

注意:早期标准库将所有功能在全局域下实现,声明在.h后缀的头文件中,使用时包含对应头文件即可,后来在std的命名空间下,和c头文件进行区分,规定c++头文件不带.h,推荐使用<iostream>+std的方式

#incllude<iostream>

using namespace std;

std命名空间的使用惯例:

std是c++标准库的命名空间

1.日常使用中,建议直接使用using namespcae std即可

2.using namespace std展开,标准库都暴露出来,自定义和库重名的类型/对象/函数就存在冲突问题,在开发项目中使用: std::cout; using std::cout展开常用的库对象/类型等方式

3.缺省参数

3.1缺省参数的概念

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

void Func(int a = 0)
{
    count<<a<<endl;
}

int main()
{
     Func();   //没有传参时,使用参数的默认值
     Func(10); //传参时,使用指定的实参

     return 0;
}

3.2缺省参数分类

  • 全缺省参数
void Func(int a = 10 ,int b = 20, int c = 30)
{
    count<<a<<endl;
    count<<b<<endl;
    count<<c<<endl;
}

  • 半缺省参数
void Func(int a, int b = 10,int c = 20)
{
    cout<<a<<endl;
    cout<<b<<endl;
    cout<<c<<endl;
}

注意:

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

int main()
{
    Fun(1);
    Func(1,2);
    Func(1,2,3);
    Fun(,20,)//err 
    //调用的时候赋值从左往右,缺省参数给的时候从右往左
}

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

//如果声明和定义同时出现,两个位置提供的值不同,编译器无法确定使用哪个缺省值

4.函数重载

4.1函数重载的概念

       函数重载:是函数的一种特殊情况,c++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似,数据不同的问题

#include<iostream>
using namespcae stdl
//1.参数类型不同
int Add(int left,int right)
{
    return left+right;
}

double Add(double left,double right)
{
    return left+right;
}

//2.参数个数不同
void f()
{
    count<<"f()"<<endl;
}

void f(int a)
{
    cout<<"f(int a)"<<endl;
}

//3.参数类型顺序不同
void f(int a,char b)
{
    ...
}

void f(char b, int a)
{
    ...
}

支持重载的原理:

        在c/c++中,一个程序运行起来需要:预处理,编译,汇编,链接

        

1.实际项目通常是由多个头文件和源文件组成,当前a.cpp中调用了b.cpp中定义的add函数时,编译后,链接前,a.o中目标文件没有add的函数地址,因为add是在b.cpp中定义的,在链接阶段处理这个问题,链接器看到a.o中调用add,但是没有add的地址,就会到b.o的符号表中找到add的地址,然后链接在一起

2.在链接时,面对add函数,去找这个函数名字(通过g++修饰的规则),编译器将函数参数类型信息添加到修改后的名字中

3.C++就是通过函数修饰来区分,只要参数不同,修饰出来的名字就不同,构成了函数重载。

4.如果两个函数,函数名和参数相同,但是返回值不同,无法构成重载,因为编译器无法区分。

5.引用

        引用不是定义了一个新变量,而是给已存在的变量取别名,编译器不会为引用变量开辟新的内存空间,它和它引用的变量共用一块内存。

void Test()
{
    int a = 10;
    int& ra = a;
}

//引用类型必须和引用实体是同种类型的

5.1 引用特性

  • 引用在定义的时候必须初始化
  • 一个变量可以有多个引用
  • 引用一旦引用一个实体,再不能引用其他实体

5.2 常引用

void Test()
{
    const int a = 10;
    // int& ra = a ; err,a为常量
    const int & ra = a;

    //int& b  = 10 ; //err,b为常量
    const int& b = 10;
    

    double d = 13.15;
    //int & rd = d; //err 类型不同
    const int& rd = d;
}

5.3引用的使用场景

  • 作参数(输出型参数,形参的改变影响实参)

    C语言中,如果使用一般形参,形参是实参的临时拷贝,则定义了指针去改变。c++中传引用。

void swap(int& r1, int&ra)
{
    ...
}

int main()
{
    int a = 0, b = 1;
    swap(a,b);
}


//递归里面,如果直接传变量,这层调用完,形参改变,
//并不会改变上一层的参数,这时候也可以使用引用
  • 作为返回值
int &Count()
{
    static int n = 0;  //n存在静态区
    n++;
    //...
    return n;
}
int Count()
{
    static int n = 0;  
 //无static n是临时变量,定义在count栈里面,出了作用域返回,
 //n不能直接给ret 此时count已经调用完成,栈帧销毁。 此时n给一个临时变量,这个临时变量作为函数的返回值 如果比较小,通常使用寄存器充当
//有static n 存在静态区,栈销毁不会影响n,n也会给一个临时变量作为返回值(不会把n直接给ret)
    n++;
    
    return n;
 }

int main()
{
    int ret = Count()
    return 0;
}

上述代码也有优化的空间,可以使用引用去作为返回值,减少拷贝。

出了作用域,它的声明周期还在,就可以使用传引用返回。

//传引用返回,产生了一个n的别名
int& Count()
{
    static int n = 0;
    n++;
    return n;
}

int main()
{
    int ret = Count();
    return 0;
}



struct Array()
{
    int a[10];
    int size;
 }AY;

//引用返回,1.减少了拷贝,返回了一个结构体的成员(出了作用域还在),
int& PosAt(AY &ay,int i)
{
    assert(i<N);
    return ay.a[i];   //出了作用域还在
}

int main()
{
    AY ay;
    PosAt(ay,1);
    //2.调用者修改了这个返回值
    for(int i = 0;i<N;i++)
    {
        count<<PosAt(ay,i)<<endl;
    }

}

总结:如果函数返回时,出了作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统,则必须使用传值返回。

传值,传引用效率比较:

        以值作为参数或者返回类型,在传参和返回期间,函数不会直接传递实参或者变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率很低,尤其当参数或者返回值类型非常大时,效率更低。

5.4引用和指针

1.在语法概念上,引用就是一个别名,没有独立空间,和其引用实体共用 一块空间,在底层实现上实际上是有空间的,因为引用是按照指针方式实现的。

2.引用是定义一个概念的别名,指针存储一个变量地址

3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

4.没有null引用,但有null指针

5.引用在定义的时候必须初始化,指针没有要求

6.在sizeof中的含义不同:引用结果为引用类型的大小,但是指针始终是地址空间所占字节个数(32位下4个字节,64位下8个字节)

7.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

8.有多级指针,但是没有多级引用

9.访问实体方式不同,指针需要显式解引用,引用编译器自己处理

10.引用比指针使用相对更安全

6.内联函数

       以inline修饰的函数叫做内联函数,编译c++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提高了程序的运行效率。

6.1内联的特性

        1.inline是一种以空间换时间的做法,如果编译器将函数当做内联函数处理,在编译阶段,会以函数体替换函数调用,优点:少了调用开销,缺点:可能使目标文件变大

        2.inline对于编译器只是一个建议,不同编译器关于inline实现机制不同,一般建议:将函数规模较小,不是递归,且频繁的调用采用inline修饰,否则会忽略inline特性。

        3.inline不要声明和定义分离,分离会导致链接错误,因为inline被展开,没有函数地址了,链接就会找不到。

7.宏

#define N 10


int add(int a, int b)
{
    ...
}

#define Add x+y
#define Add ((x)+(y))

宏的优点:

1.增强代码的复用性

2.提高性能

宏的缺点:

1.不方便调试宏(在预编译阶段进行了替换)

2.导致代码的可读性差,可维护性差,容易误用

3.没有类型安全的检查

C++中可以替代宏:

1.定义常量 换用const,enum. 

2.短小函数换位inline

8.auto关键字(c++11)

     随着程序越来越复杂,程序中用到的类型也更复杂,经常体现在:

       1.类型难于拼写

        2.含义不明确导致错误

      auto 关键字 可以自动推导出变量的类型。使用auto定义变量时,必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。

8.1 auto的使用细则

1.auto与指针和引用结合起来使用

用auto声明指针类型时,用auto和auto*相同,但是auto在声明引用类型时,必须加&

int x = 10;
auto a = &x;
auto* b =&x;
auto&c = x;

2.在同一行定义多个变量

当在同一行声明多个变量的时候,这些变量必须是相同的类型,否则编译器会报错,因为编译器只对第一个类型进行推到,然后用推出来的类型定义其他变量

auto a = 1, b = 2;
auto c = 3, d = 4.0 //err

3.auto不能推的场景

  • auto不能作为函数的参数
  • auto不能用来声明数组

9.基于范围的for循环(语法糖)

9.1范围for的语法

//常规的for循环
void Testfor()
{
    int arr[] = {1,2,3,4,5};
    for(int i =0; i<sizeof(arr)/sizeof(arr[0];++i)
        arr[i] *=2;
    
    for(int *p = arr ;p<array+sizeof(arr)/sizeof(arr[0]);++p)
        cout<<*p<<endl;
}

对于一个有范围的结合,由程序员说明循环的范围是多余的,有时候还会出错,在c++11中引入了基于范围的for循环,for循环后的括号由冒号:分为两部分,第一部分是范围内用于迭代的变量,第二部分是表示被迭代的范围

int arr[] = {1,2,3,4,5};
for(auto& e:array)
    e*=2;

for(auto e:array)
    cout<<e<<endl;

9.2范围for的使用条件

1.for循环的迭代返回必须是已知的

2.迭代的对象要实现++和==的操作(后续迭代器中说明)

10.指针空值--nullptr(c++11)

        NULL实际上是一个宏,表示0,有时候初始化为null和0会有歧义,所以新定义了一个关键字nullptr(关键字)


总结

本文主要讲了c++中的一些关键字和小知识点,能力有限,有错误请指正。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C入门PDF是一种提供初学者学习C语言基础知识的电子文档。C语言被广泛应用于软件开发领域,是一种高级计算机编程语言。学习C语言是许多计算机科学专业学生和编程爱好者的首选。 C入门PDF通常包含基本的C语言语法和常用的编程概念。它们可能包括变量、数据类型、运算符、条件语句、循环语句和函数等基础知识的介绍。此外,它们还可能包含一些简单的编程示例和练习,帮助初学者理解并应用所学知识。 通过学习C入门PDF,初学者可以逐步建立对C语言的理解和掌握。他们可以学习如何编写简单的C程序,并逐渐提高他们的编程能力。C语言是一种结构化的编程语言,因此通过学习C语言,初学者也可以培养良好的编程习惯和逻辑思维能力。 对于初学者来说,C入门PDF是一个方便而有效的学习工具。他们可以根据自己的进度和需要,在任何时间和地点学习C语言。通过自主学习,初学者可以在自己的学习节奏和理解能力下进行学习,不受时间和空间的限制。 C入门PDF是许多在线教育平台、编程社区和计算机科学教育机构提供的免费资源。因此,初学者可以轻松获取这些资源,并根据自己的学习需求选择最适合自己的C入门PDF。 总之,C入门PDF是一种方便且有效的学习资源,可以帮助初学者掌握C语言的基础知识和编程技能。通过学习C语言,初学者可以为自己的编程之路打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值