C++入门

1.命名空间

(1)命名空间定义

使用namespace关键字,后面跟命名空间的名字,然后接一对{}

//普通命名空间
namespace N1
{
    int a;
    int Add(int left,int right)
    {
       	return left+right;
    }
}
//命名空间可以嵌套
namespace N2
{
    int a;
    int b;
    int Add(int left,int right)
    {
       	return left+right;
    }
    namespace N3
    {
        int c;
    	int d;
    	int Add(int left,int right)
    	{
      	 	return left+right;
  	    }
    }
}
//同一个项目中可以有多个相同名称的命名空间,编译器最后会合成到一个命名空间中
namespace N1
{
    int Mul(int left,int right)
    {
        return left+right;
	}
}
  • 一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中

(2)命名空间使用

namespace N
{
	int a = 10;
	int b = 20;
 	int Add(int left, int right)
    {
 		return left + right;
	}
}

int main()
{
    printf("%d\n",a);//编译出错,无法识别a
    return 0;
}
//1.加命名空间名称及作用域限定符
int main()
{
	printf("%d\n",N::a);   
}
//2.使用using将命名空间中成员引入
using N::b;
int mian()
{	
    printf("%d\n",N::a);
    printf("%d\n",b);
}
//3.使用using namespace 命名空间名称引入
using namespace N;
int main()
{
    printf("%d\n",N::a);
    printf("%d\n",b);
    Add(10,20);
    return 0;
}

2.输入输出

使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含< iostream >头文件以及std标准命名空 间。

#include<iostream>
using namespace std;

int main()
{
    int a,b;
    
    cin>>a;//输入给a
    cout<<b;//将b输出    
    cout<<b<<endl;//先输出b再换行
   
   	return 0;
}
  • c++中输入输出不需要关心数据的格式
3.缺省参数
void TestFunc(int a = 0)
{
 	cout<<a<<endl;
}
int main()
{
 	TestFunc(); // 没有传参时,使用参数的默认值
 	TestFunc(10); // 传参时,使用指定的实参
}

  • 半缺省参数必须从右往左依次来给出,不能间隔着给
void TestFunc(int a, int b = 10, int c = 20)
  • 缺省参数不能在函数声明和定义中同时出现

4.函数重载

在同一个作用域中,函数名必须相同,参数必须不同

​ 参数列表不同:

​ 1.参数个数

​ 2.参数类型

​ 3.类型的次序

​ 与返回值类型无关

  • extren"C": 意思是告诉编译器, 将该函数按照C语言规则来编译

5.引用

(1).概念:

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

void TestRef()
{
    int a=10;
    int& ra= a;
    
    printf("%p",&a);
   	printf("%p",&ra);
}
  • 引用类型必须和引用实体是同种类型的

(2).特性

​ a.引用在定义时必须初始化

​ b.一个变量可以有多个引用

​ c.引用一旦引用一个实体,再不能引用其他实体

void TestRef()
{
    int a=10;
    //int& ra;错误,没有初始化
    int& ra=a;
    int& rra=a;
    printf("%p %p %p",&a,&ra,&rra);
}

(3).常引用

int main()
{
    int a=10;
    const int& ra=a;//不能通过ra来修改a
        
//  int& rb=100;//100是字面常量,不能被修改
    const int& rb=100;
    
    const int c=10;
//  int& rc=c;//编译失败----c是常量,给成普通类型的引用不行
    const int& rc=c;
        
    double d=12.34;
//	int& rd=d;//编译错误
    const int& rd=d;//rd不是d的引用,而是double到int发生了隐式类型转换,同时创建了一个临	 时变量存储转化的结果(12),rd引用的是这个临时变量
}

(4)使用场景

a.作参数

void Swap(int& left, int& right)
{
 int temp = left;
 left = right;
 right = temp;
}
  • 如果引用传参,函数不想通过形参改变实参,最好将形参设置为const类型的引用

b.作返回值

int& Count()
{
 static int n = 0;
 n++;
 // ...
 return n;
}
  • 如果函数返回时,出了函数作用域,如果返回对象还未还给系统(全局变量或static修饰),则可以使用引用返回,如果已经还给系统了(临时变量 ),则必须使用传值返回。

(5)传值、传地址、传引用效率区别

​ 结论:转值效率低,传地址和传引用差不多

(6)指针和引用的区别:

相同点

​ a.效率差不多

​ b.传参可以达到相同的效果-->修改形参可以改变实参

​ c.底层实现方式一样

不同点:

​ a.引用在定义时必须初始化,指针无要求

​ b.引用在初始化一个实体后,就不能在引用别的实体了,指针无要求

​ c.没有NULL引用,但有NULL指针

​ d.sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间的大小

​ e.引用自加即引用的实体加1,而指针自加是指针向后偏移一个类型的大小

​ f.没有多级引用,有多级指针

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

​ h.引用比指针更加安全

6.内联函数&宏

(1)宏

​ 宏: #define出来的东西

​ 宏常量:#define MAX_SIZE 100

​ 宏函数:#define MAX(a,b) a>b?a:b

(2)const

​ a.C++中被const修饰的变量,已经不是变量了,而是一个常量,允许用来定义数组

const int a=10;
//int array[a]   可证明a为常量
//a=100;   报错
int* pa=(int*)&a;
*pa=100	//可通过指针修改a中的值

​ b.const具有宏替换的属性

(3)内联函数

以inline修饰的函数叫内联函数,编译时c++编译器会在调用内联函数的地方展开内联函数提升程序运行的效率

(4)特性

​ a.在编译时:会展开该函数

​ b.函数如果是递归、循环等比较复杂,就会忽略inline

​ c.inline不建议声明和定义分离,分离会导致链接错误

总结

宏的优点:

​ 1.提高了程序的可读性,同时也方便进行修改

​ 2.提高程序的运行效率:使用带参的宏定义既可完成函数调用的功能,又能避免函数的出栈与入栈操作,减少系统开销,提高运行效率

​ 3. 宏是由预处理器处理的,通过字符串操作可以完成很多编译器无法实现的功能。比如##连接符

宏的缺点:

​ 1.由于是直接嵌入的,所以 代码可能相对多一点

​ 2.嵌套定义过多可能会影响程序的可读性,而且很容易出错

​ 3.对带参的宏而言,由于是直接替换,并不会检查参数是否合法,存在安全隐患

  • 预编译语句仅仅是简单的值代替,缺乏类型的检测机制。这样预处理语句就不能享受C++严格的类型检查的好处,从而可能成为引发一系列错误的隐患。的确,宏定义给我们带来很多方便之处,但是必须正确使用,否则,可能会出现一些意想不到的问题。

宏和内联函数的区别

1.内联函数相比较于宏而言,内联函数要做参数类型检查,从而内联函数相比宏而言更加安全

2.内联函数在运行时可调试,而宏定义不可以。

7.auto关键字

(1)概念:

auto声明的变量可以由编译器在编译阶段推导而得(根据初始化表达式来推导)

(2)特性:

​ a.用auto声明指针类型时,auto和auto*无区别;auto修饰引用时,auto是拷贝,auto&是实体

​ b.auto修饰的变量不能用作函数参数

​ c.auto不能声明数组

​ d. 当在同一行声明多个变量时,这些变量必须是相同的类型,

范围for

1.语法

int mian()
{
    int array[]={1,2,3,4,5};
    for(auto&e:array)
        e*=2;
    for(auto e:array)
        cout<<e<<" "<<endl;
}

2.使用条件

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

nullptr关键字

int* p=nullptr;//创建一个空指针