C++ 入门超详解!

目录

  • 1.命名空间
    • 1.1命名空间简介
    • 1.2代码示例:
  • 2.c++输入输出
  • 3.缺省参数
    • 3.1缺省参数简介
    • 3.2全缺省
      • 3.2.1全缺省代码示例
    • 3.3半缺省
      • 3.3.1半缺省代码示例
  • 4.函数重载
    • 4.1c++函数重载的定义
    • 4.2函数重载的作用
    • 4.3c++函数重载的原理
    • 4.4为什么c语言不能实现函数重载
    • 4.5代码示例
      • 4.5.1c函数重命名图例
      • 4.5.2C++函数重命名图例
  • 5.引用
    • 5.1引用简介
    • 5.2引用特点:
    • 5.3引用和const
    • 5.4引用和指针
  • 6.内联函数
    • 6.1内联函数简介
    • 6.2内联函数优点
    • 6.3内联函数缺点
  • 7.auto关键字与基于范围的for循环
    • 7.1auto简介
      • 7.1.1简单的识别变量类型
    • 7.2auto迭代
      • 7.2.1auto& 可以对数组 a 中的元素进行修改
    • 7.3auto特性
  • 8.指针空值nullptr
    • 8.1nullptr简介
    • 8.2NULL和nullptr示例

1.命名空间

1.1命名空间简介

  1. 命名空间随标准C++而引入,相当于一个灵活的文件域(全局域),以关键字namespace开头给其起个名字,并用大括号把定义区域括起来(声明块)。
  2. 在域外使用域内成员时,需要加上命名空间名作为前缀,再加上域操作符“::”,可以使用嵌套定义。
  3. 如果在关键字namespace之前使用using,就不必使用限定修饰名,即可以一次性使命名空间中所有成员都可以直接被使用。

标准C++库中所有组件都在std的命名空间中声明和定义的,在标准C++平台调用如下语句:
using namespace std;

1.2代码示例:

using namespace std; //展开命名空间
namespace Name  //定义Name命名空间
{
     
	int a = 10;
	int sub(int x, int y) 
	{
     
		return x - y;
	}
	namespace N1  //命名空间嵌套
	{
     
		int b = 5;
	}
}

2.c++输入输出

  1. 使用输入和输出需要头文件iostreamm;
    #include
  2. 输入 cin>> a>>endl;
    cin>>"输入a的值为:" >>endl;
  3. 输出 cout< cout<<"输出a的值为:" <

3.缺省参数

3.1缺省参数简介

  1. 在C语言中,函数没有指定参数列表,默认可以接收任意多个参数,但在C++中,因为严格的参数类型检测,没有参数列表的函数,默认为void,不接收任何参数。
  2. 缺省参数:缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用函数时,如果没有指定实参则采用该默认值,否者使用指定的实参。

3.2全缺省

全缺省:全缺省参数所有参数都有默认值,如果没有手动传参,那么编译器会使用默认参数列表中的参数。但是这里值得注意的是,如果传参的时候只传了部分参数,那么该值会被从左至右匹配。

3.2.1全缺省代码示例

void test(int a = 1,int b = 2, int c = 3)
{
     
    cout << a << " " << b << " " << c << endl;
}

3.3半缺省

半缺省:一部分参数有默认值:从右往左依次给值

3.3.1半缺省代码示例

void test(int a ,int b = 2, int c = 3)
{
     
    cout << a << " " << b << " " << c << endl;
}

4.函数重载

4.1c++函数重载的定义

  • 在同一作用域类,一组函数的函数名相同,参数列表不同(参数个数不同/参数类型不同),返回值可同可不同

4.2函数重载的作用

  • 重载函数通常用来在同一个作用域内 用同一个函数名 命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

4.3c++函数重载的原理

  • 编译器在编译.cpp文件中当前使用的作用域里的同名函数时,根据函数形参的类型和顺序会对函数进行重命名(不同的编译器在编译时对函数的重命名标准不一样)但是总的来说,他们都把文件中的同一个函数名进行了重命名;
  • 在vs编译器中
    根据返回值类型(不起决定性作用)+形参类型和顺序(起决定性作用)的规则重命名并记录在map文件中。
  • 在linux g++ 编译器中
    根据函数名字的字符数+形参类型和顺序的规则重命名记录在符号表中;从而产生不同的函数名,当外面的函数被调用时,便是根据这个记录的结果去寻找符合要求的函数名,进行调用;

4.4为什么c语言不能实现函数重载

  • 编译器在编译.c文件时,只会给函数进行简单的重命名;具体的方法是给函数名之前加上”_”;所以加入两个函数名相同的函数在编译之后的函数名也照样相同;调用者会因为不知道到底调用那个而出错;

4.5代码示例

int Add(int a,int b)
{
     
   return a+b;
}
float Add(float a,float b)
{
     
    return a+b;
}

4.5.1c函数重命名图例

在这里插入图片描述

4.5.2C++函数重命名图例

在这里插入图片描述

5.引用

5.1引用简介

  • 引用是给一个已经定义的的变量取别名,而不是定义一个新的变量。
  • 引用定义格式 :类型& 引用变量名 = 已定义变量

5.2引用特点:

  1. 多个变量可以引用一个变量
int a = 10;
int& b = a;
int& c = a;
cout<<a<<" "<<b<<" "<<c<<endl; // 10 10 10
  1. 引用必须初始化
int& a; // 语法错误
  1. 引用只能在初始化的时候引用一次,不能在改变为引用其他的变量

  2. 常量不能被引用

int& a = 10; // 语法错误
const int& a = 10; // 正确,常量具有常性,只有常引用可以引用常量
cout<<a<<endl; // 10

5.3引用和const

#include 
using namespace std;
 
int main()
{
     
    int a1 = 10;
    cout<<a1<<endl; // 10
    
    const int& a2 = a1;
    cout<<a1<<" "<<a2<<endl; //10 10 
       
    a1 = 5;
    cout<<a1<<" "<<a2<<endl; //5 5  ai的值改变,a2的值也会改变
     
    const int a3 = 10;
    const int& a4 = a3;
    //int& a5 = a3; // 报错
    const int& a6 = 5; // 常量具有常性,只有常引用可以引用常量
    
    float a7 = 10.10;
    //int& a8 = a7; // 报错,a7是float类型,a8是int型,a7给a8赋值会产生一个临时变量,
                // 即a7引用的是这个带有常性的临时变量,所以不能赋值
    const int& a9 = a7;
    return 0;
}

5.4引用和指针

  1. 引用是变量别名,指针保存变量的地址,二者其实有异曲同工之妙,都是直接指向对象的内存块,但是引用和指针还是有诸多不同。例如

    a) 引用必须初始化;指针可以不初始化

    b) 引用只能在定义时初始化一次,之后不能改变指向其他变量;指针指向的对象可以改变

    c) 引用不能为空,必须指向有效对象;指针可以为空

    d) sizeof指针和引用的含义不同。sizeof引用对象得到的是引用所指对象的大小;sizeof指针变量得到的是对象地址大小

    e) 引用和指针自增自减意义不同

    f) 引用比指针安全

    5、使用引用时的注意事项

    a) 不要返回一个临时变量的引用

    b) 不要返回函数内部new分配的内存的引用

6.内联函数

6.1内联函数简介

  1. 在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。

6.2内联函数优点

  1. 不会发生函数调用开销。
  2. 当调用函数时,它还节省了推送/弹出变量在堆栈上的开销。
  3. 它还节省了函数返回调用的开销。
  4. 内联函数时,可以使编译器对函数体执行特定于上下文的优化。 对于正常的函数调用,这种优化是不可能的。 通过考虑调用上下文和被调用上下文的流程,可以获得其他优化。
  5. 对于嵌入式系统,内联函数可能很有用(如果它很小),因为内联可以产生比函数调用前导码和返回更少的代码。

6.3内联函数缺点

除了通常使用内联扩展可能带来的问题,作为一种编程语言特性的内联函数也可能并没有看起来那么有效,原因如下:

  1. 通常,设计编译器的程序设计者比大多数的程序设计者更清楚对于一个特定的函数是否合适进行内联扩展;一些情况下,对于程序员指定的某些内联函数,编译器可能更倾向于不使用内联甚至根本无法完成内联。
  2. 对于一些开发中的函数,它们可能从原来的不适合内联扩展变得适合或者倒过来。尽管内联函数或者非内联函数的转换易于宏的转换,但增加的维护开支还是使得它的优点显得更不突出了。
  3. 对于基于C的编译系统,内联函数的使用可能大大增加编译时间,因为每个调用该函数的地方都需要替换成函数体,代码量的增加也同时带来了潜在的编译时间的增加。

7.auto关键字与基于范围的for循环

7.1auto简介

  • 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量
    C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

7.1.1简单的识别变量类型

C++ 入门超详解!_第1张图片
C++ 入门超详解!_第2张图片

7.2auto迭代

  • 对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围
    C++ 入门超详解!_第3张图片
    在这里插入图片描述

7.2.1auto& 可以对数组 a 中的元素进行修改

C++ 入门超详解!_第4张图片
在这里插入图片描述

7.3auto特性

1.auto不能作为函数参数
2.auto不能直接声明数组
3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法
4. auto在实际中最常见的优势用法就是跟以后会讲到的C++11提供的新式for循环,还有lambda表达式等进行配合使用。
5. auto不能定义类的非静态成员变量
6. 实例化模板时不能使用auto作为模板参数

8.指针空值nullptr

8.1nullptr简介

  • 从1972年C语言刚刚诞生以来,常数0就扮演着整数(int)0和空指针( null pointer )两种角色。为了避免理解上的二义性,C语言通常使用NULL宏来表示空指针,NULL宏通常被定义为(void *)0或0, 而C++仅仅采用0来表示空指针,这样存在一个问题:比如对于重载函数 fun(char *) 和 fun(int) 的调用来说,若直接用NULL作为参数调用fun(NULL),我们可能认为NULL作为空指针的表示,应该调用 fun(char *) 函数,然而NULL实际上的值为0,就会调用 fun(int) 。 nullptr 关键字正是为了解决这一问题而产生的。
    nullptr 能够转换成任何指针类型(包括成员函数指针和成员变量指针)和bool类型(这是为了兼容普通指针都能使用 if(ptr) 判断是否为空指针的形式),但是不能被转换为整数0。

8.2NULL和nullptr示例

#include 
using namespace std;
 
void func(void* i)
{
     
	cout << "func1" << endl;
}
 
void func(int i)
{
     
	cout << "func2" << endl;
}
 
void main(int argc,char* argv[])
{
     
	func(NULL);
	func(nullptr);
	getchar();
}

在这里插入图片描述
总结

NULL在C++中就是0,这是因为在C++中void*
类型是不允许隐式转换成其他类型的,所以之前C++中用0来代表空指针,但是在重载整形的情况下,会出现上述的问题。所以,C++11加入了nullptr,可以保证在任何情况下都代表空指针,而不会出现上述的情况,因此,建议以后还是都用nullptr替代NULL吧,而NULL就当做0使用。

你可能感兴趣的:(笔记,C/C++,c++)