【C++初阶】C++入门

目录

【前言】

1、C++关键字(C++98)

2、命名空间

2.1 namespace定义命名空间

2.2 命名空间的使用

3、C++输入和输出

4、缺省参数

5、函数重载

5.1 C++支持函数重载的原理——名字修饰

6、引用

6.1 引用概念

6.2 引用特性:

6.3 常引用

6.4 使用场景

6.5 引用和指针的区别

7、内联函数

8、auto关键词(C++11)

8.1 auto的使用细则

8.2 auto不能推导的场景

9、基于范围的for循环(C++11)

9.1 范围for的使用条件

10、nullptr空指针(C++11)


【前言】

C++是在C的基础上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。

1、C++关键字(C++98)

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

2、命名空间

  • C/C++中,变量、函数和类都是大量存在的,这些变量名、函数名和类名存在于全局作用域中,可能会导致很多冲突。
  • 举个例子:小组成员分工写一个项目,不同程序员可能命名了相同名称的变量或者函数,而这些又是作用于全局的,当程序放到一起去运行时,就会产生重定义冲突。
  • 使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染。

2.1 namespace定义命名空间

namespace 命名空间名

{

     // 命名空间成员

     // 命名空间中可以定义变量/函数/类型

     int rand = 10;

     int Add(int a,int b)

     {

          return a + b;

      }

      struct Node

      {

           int val;

           struct Node* next;

       };
}

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

namespace smile
{
	int a = 0;
	int b = 1;

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

	struct Node
	{
		int val;
		struct Node* next;
	};

}
  1. 命名空间可以嵌套定义(即一个命名空间里可以再定义其他的命名空间)。
  2. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成在同一个命名空间中(ps:一个工程中的test.h和test.cpp中的N1会被合并成一个)。

2.2 命名空间的使用

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

  • 加命名空间名称及作用域限定
int main()
{
	printf("%d\n", smile::a);
	return 0;
}
  • 使用using将命名空间中某个成员引入
using smile::b;
int main()
{
	printf("%d\n", b);
	return 0;
}
  • 使用using namespace 命名空间名称 引入
using namespace smile;
int main()
{
	printf("%d\n", smile::a);
	printf("%d\n", b);
	return 0;
}

std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中。

3、C++输入和输出

  1. cout标准输出对象(控制台)和cin标准输入对象(键盘)是全局的流对象,使用时,必须包含<iostream>头文件以及按命名空间方法使用std。
  2. <<是流插入运算符>>是流提取运算符

4、缺省参数

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

4.1 缺省参数分类

  • 全缺省参数:所有形参都给了缺省值。
void Func(int a = 1, int b = 2, int c = 3)
{
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
} 
  • 半缺省参数:给出部分缺省值

注意:

1、半缺省参数必须从右往左依次给出,不能间隔着给(即给了缺省值的必须在无缺省值的右边,否则会出现以下问题)。

//错误案例
void Func(int a = 10, int b = 20, int c)//有缺省值的出现在无缺省值的左边
{
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
} 

int main
{
    Func(20);//这样调用的时候,20应该传给有有缺省值的a,还是无缺省值的c呢?
             //按照从左向右的传参顺序应该传给a,但c又没有默认缺省值,这样就会导致c没有值,编译器报错
    return 0;
}

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

因为当两个位置给的缺省值不一样时,编译器无法确定该用哪个缺省值。

3、缺省值必须是常量或全局变量。

4、C语言不支持缺省参数(编译器不支持)。

5、函数重载

函数重载:

1、解决的是同一个函数名有着不同的功能的问题。

2、C++允许在同一作用域中声明几个功能类似的同名函数

3、构成函数重载的条件:形参列表(形参个数 或 类型 或 类型顺序)不同

注意:函数返回值类型不同不构成重载。

//1、形参个数不同
void f()
{
	cout << "f()" << endl;
}

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

//2、形参类型不同
int Add(int left, int right)
{
	return left + right;
}

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

//3、形参类型顺序不同
void f(int a, char b)
{
	cout << "f(int a, char b)" << endl;
}

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

5.1 C++支持函数重载的原理——名字修饰

  • 程序运行要经历几个阶段:预处理、编译、汇编、链接
  • 多个文件,隔离编译,一起链接,编译后函数名可能会改变,链接会去寻找所调用的函数。
  • C编译器没有对形参列表不同的同名函数进行修饰,所以同名函数链接时,链接器无法区分链接哪个函数。
  • C++编译器:编译器将函数形参列表信息添加到修饰后的名字中,这样链接器就可以区别同名但不同形参列表的函数了。
  • c++通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

6、引用

6.1 引用概念

1、给已存在的变量取个别名,它和它引用的变量共用同一块内存空间

2、形式:类型& 引用变量名 = 引用实体

3、引用类型必须和引用实体同类型

6.2 引用特性:

1、引用在定义时必须初始化

2、一个变量可以有多个引用

3、引用一旦引用一个实体,便不能再引用其他实体。

6.3 常引用

1、引用过程中,权限不能放大

const int a = 0;

int& b = a; //错误

2、但权限可以平移或缩小

int x = 0;

int& y = x; //一个变量可以有多个引用

const int& z = x;

++x; //可以

++z; //不可以

3、类型转换时会产生临时变量,临时变量具有常性(相当于const修饰)

double dd = 1.11;

int ii = dd;

int & rii = dd; //不可以,dd拷贝给int临时变量,临时变量再取别名为rii,这个过程权限放大了,从const int型放大成了int型的。

const int& rii = dd; //可以,权限的平移。

6.4 使用场景

1、做参数

//引用做参数
void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}

意义:对于大对象、深拷贝类对象,可以减少拷贝,提高效率。

2、做返回值

//引用做返回值
int& Count()
{
	static int n = 0;
	n++;
	//...
	return n;
}
  • 传值返回要生成临时变量,传的值拷贝给临时变量,临时变量在做返回值给接收变量
  • 传引用返回:对于大对象、深拷贝类对象,传引用返回,不会再生成临时变量,这样可以减少拷贝,提高效率。

总结:

1、基本任何场景都可以用引用传参。

2、谨慎用引用做返回值:函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果不在了(还给系统了),则必须使用传值返回。

6.5 引用和指针的区别

  • 语法层面:引用不开空间,是取别名。
  • 底层汇编指令实现的角度:引用是类似指针的方式实现的。

引用和指针的不同点:

1、引用是给变量取别名指针变量地址

2、引用在定义时必须初始化,指针没有要求。

3、引用一旦确定引用实体,便不能再引用其他实体。而指针可以在任何时候指向任何一个同类型实体。

4、没有NULL引用,但有NULL指针。

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

6、引用自加即引用的实体值加1,指针自加即指针向后偏移一个类型的大小。

7、有多级指针,但没有多级引用。

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

9、引用比指针使用起来相对更安全。

7、内联函数

  • 内联函数以inline修饰的函数,编译时C++编译器会在调用内联函数的地方展开函数定义代码
  • 好处没有函数调用建立栈帧的开销,提升程序运行的效率。
  • 适用短小的频繁调用的函数。inline对于编译器仅仅只是一个建议,最终是否成为inline,编译器自己决定。
  • 建议:inline函数的声明和定义不要分开

8、auto关键词(C++11)

auto自动推导类型,根据右边自动推导左边。

注意:

  • 使用auto定义变量时必须对其进行初始化,在编译阶段编译器需根据初始化表达式来推导auto的实际类型
  • auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译时会将auto替换为变量实际的类型。

8.1 auto的使用细则

1、auto与指针/引用结合使用:用auto声明指针类型时,用auto和auto*没有任何区别,但是auto声明引用类型时则必须加&。

int x  =10;

举例:

  • auto a = &x; //可以,因为右边x加了取地址符,编译器较容易推出左边a的类型。
  • auto* b = &x;//可以
  • auto c = x;//这样就不是引用类型取别名,而是int类型定义c
  • auto& c = x;//正确的引用

2、在同一行定义多个变量,auto必须始终推导为同一类型。

8.2 auto不能推导的场景

1、auto不能作为函数形参类型

  • void TestAuto(auto a) { } //错误

2、auto不能直接用来声明数组

  • void TestAuto(auto a)
  • {
  •         int a[ ] = {1, 2, 3};
  •         auto b[ ] = {4, 5, 6 };
  • }

9、基于范围的for循环(C++11)

  • 说明:对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时还容易犯错。因此C++11中引入了基于范围的for循环。
  • 形式:for循环后的括号内由冒号:分为两部分,第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

9.1 范围for的使用条件

1、for循环迭代的范围必须是确定的

对于数组而言,就是数组中第一个元素和最后一个元素的范围。

2、迭代的对象要实现++和==的操作。

10、nullptr空指针(C++11)

  • NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量
  • 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++作为新关键字引入的。
  • 在C++11中,sizeof(nullptr)与sizeof((void*)0)所占的字节数相同
  • 为了提高代码的健壮性,在后续表示指针空值最好使用nullptr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值