C++初阶(关键字、命名空间、缺省参数、函数重载、引用等)简版

目录

一、关键字

二、命名空间

2.1 命名空间的定义 

 2.2 命名空间的使用 

 三、缺省参数

 3.1 缺省类型

3.2 缺省注意事项

四、函数重载 

4.1 函数重载的概念

五、引用

5.1 引用的特性 

5.2常引用

5.3引用&的应用

5.3.1做参数

5.3.2 做返回值

5.4 传值、传引用效率比较

5.5 引用&与指针的区别

六、内联函数

6.1内联函数概念

6.2内联的特性 

七、auto关键字 

7.1 auto前言

7.2 auto使用细则

7.3 auto雷点


一、关键字

在这里我们只要知道有多少关键字即可,不必准确知道每一个关键字的含义,在学习C++的时候逐步会提到每一个关键字再深入了解

二、命名空间

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

2.1 命名空间的定义 

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

定义模板:

 namespace 空间名                                关键字 + 空间名 + { 内容 }

{                                                               这块内容只有在这个空间内才能被找到

        内容                                                命名空间也可以嵌套,但并不推荐

}                                                                                   

 2.2 命名空间的使用 

#include <stdio.h>
#include <stdlib.h>
// fun是命名空间的名字,一般开发中是用项目名字做命名空间名。
// 1. 正常的命名空间定义
namespace fun
{
	// 命名空间中可以定义变量/函数/类型
	int rand = 10;
	int Add(int left, int right)
	{
		return left + right;
	}
		struct Node
	{
		struct Node* next;
		int val;
	};
}
int main()
{
	printf("%d\n", fun::rand);
	return 0;
}

在调取rand的时候要把在其前面加上空间名::表示在某个特定的空间里定义的某量

没有空间名::同样会报错

 三、缺省参数

缺省参数是 声明或定义函数时 为函数的 参数指定一个缺省值 。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。
#include<iostream>
using namespace std;

void Func(int a = 0) {
	cout << a << endl;
}
int main()
{
	Func();//    没有传参时,使用参数的默认值
	Func(10);//  传参时,使用指定的实参
	return 0;
}

 3.1 缺省类型

全缺省参数

void Func(int a = 10, int b = 20, int c = 30)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }

 半缺省参数

void Func(int a, int b = 10, int c = 20)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }

3.2 缺省注意事项

1. 半缺省参数必须 从右往左依次 来给出,不能间隔着给
                    ××××         func(a,,c)      ××××   错误!
2. 缺省参数不能在函数声明和定义中同时出现
  //a.h
  void Func ( int a = 10 );
  // a.cpp
  void Func ( int a = 20 )
 {}
3. 缺省值必须是常量或者全局变量
4. C 语言不支持(编译器不支持)

四、函数重载 

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被
了。

4.1 函数重载的概念

函数重载: 是函数的一种特殊情况, C++ 允许在 同一作用域中 声明几个功能类似 的同名函数 ,这些同名函数的形参列表 ( 参数个数 或 类型 或 类型顺序 ) 不同 ,常用来处理实现功能类似数据类型不同的问题。
#include<iostream>
using namespace std;
//形参列表的类型不同
int Add(int left, int right) {
 cout << "int Add(int left, int right)" << endl;
 return left + right; 
}
double Add(double left, double right) {
 cout << "double Add(double left, double right)" << endl;
 return left + right; 
}
//形参列表的数量不同
void f()
{
 cout << "f()" << endl; 
}
void f(int a)
{
 cout << "f(int a)" << endl; 
}
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 引用的特性 

1. 引用在 定义时必须初始化
2. 一个变量可以有多个引用(取多个别名)
3. 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{
   int a = 10;
   // int& ra;   // 该条语句编译时会出错
   int& ra = a;
   int& rra = a;
   printf("%p %p %p\n", &a, &ra, &rra);  
}

5.2常引用

void TestConstRef()
{
    const int a = 10;
    //int& ra = a;   // 该语句编译时会出错,因为int&形内容可以被改变,但a为常数所以报错
    const int& ra = a;
    // int& b = 10; // 该语句编译时会出错,10为常量,不能赋给可以修改的int&
    const int& b = 10;
    double d = 12.34;
    //int& rd = d; // 该语句编译时会出错,类型不同
    const int& rd = d; 
}

5.3引用&的应用

5.3.1做参数

void Swap(int& left, int& right) {
   int temp = left;
   left = right;
   right = temp; 
}

5.3.2 做返回值

int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n; 
}

实验如下代码

int& Add(int a, int b) {
    int c = a + b;
    return c; }
int main()
{
    int& ret = Add(1, 2);
    Add(3, 4);
    cout << "Add(1, 2) is :"<< ret <<endl;
    return 0; 
}
注意: 如果函数返回时,出了函数作用域,如果返回对象还在 ( 还没还给系统 ) ,则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回。
在下面这段代码中
int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n; 
}
静态变量n存储在堆区当中,所以调用函数创建的栈帧并不会销毁n,可以作为int&返回

5.4 传值、传引用效率比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直 接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效 率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
#include <time.h>
struct A{ int a[10000]; };
void TestFunc1(A a){}
void TestFunc2(A& a){}
void TestRefAndValue()
{
 A a;
 // 以值作为函数参数
 size_t begin1 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc1(a);
 size_t end1 = clock();
 // 以引用作为函数参数
 size_t begin2 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc2(a);
 size_t end2 = clock();
// 分别计算两个函数运行结束后的时间
 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
 cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl; 
}

5.5 引用&与指针的区别

1. 引用概念上定义一个变量的别名 指针存储一个变量地址
2. 引用 在定义时 必须初始化 指针没有要求
3. 引用 在初始化时引用一个实体后,就 不能再引用其他实体 ,而指针可以在任何时候指向任何 一个同类型实体 
4. 没有 NULL 引用 ,但有 NULL 指针
5. sizeof 中含义不同 引用 结果为 引用类型的大小 ,但 指针 始终是 地址空间所占字节个数 (32 位平台下占4 个字节 )
6. 引用自加即引用的实体增加 1 ,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同, 指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全

六、内联函数

6.1内联函数概念

inline 修饰 的函数叫做内联函数, 编译时 C++ 编译器会在 调用内联函数的地方 展开 ,没有函数调用建立栈帧的开销, 内联函数提升程序运行的效率。
#include<iostream>
using namespace std;
inline int Add(int a, int b) {
	return a + b;
}

int main() {
	int ret = 0;
	ret = Add(1,2);
	return 0;
}

6.2内联的特性 

1. inline 是一种 以空间换时间 的做法,如果编译器将函数当成内联函数处理,在 编译阶段,会
用函数体替换函数调用 缺陷 :可能会使目标文件变大, 优势 :少了调用开销,提高程序运
行效率。
2. inline 对于编译器而言只是一个 建议 ,不同编译器关于 inline 实现机制可能不同 ,一般建
议:将 函数规模较小 ( 即函数不是很长,具体没有准确的说法,取决于编译器内部实现 )
是递归、且频繁调用 的函数采用 inline 修饰,否则编译器会忽略 inline特性。
3. inline不建议声明和定义分离 ,分离会导致链接错误。因为 inline 被展开,就没有函数地址
了,链接就会找不到

七、auto关键字 

7.1 auto前言

随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:
1. 类型难于拼写
2. 含义不明确导致容易出错
#include <string>
#include <map>
int main()
{
 std::map<std::string, std::string> m{ { "apple", "苹果" }, { "orange", "橙子" },        
    {"pear","梨"} };
 std::map<std::string, std::string>::iterator it = m.begin();
 while (it != m.end())
 {
 //....
 }
 return 0; 
}
std::map<std::string, std::string>::iterator 是一个类型,但是该类型太长了,特别容
易写错。
在编程时,常常需要把表达式的值赋值给变量,这就要求在声明变量的时候清楚地知道表达式的 类型。然而有时候要做到这点并非那么容易,因此C++11 auto 赋予了新的含义
【注意】
使用 auto 定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导 auto
的实际类型 。因此 auto 并非是一种 类型 的声明,而是一个类型声明时的 占位符 ,编译器在编
译期会将 auto 替换为变量实际的类型。

7.2 auto使用细则

1. auto 与指针和引用结合起来使用
auto 声明 指针类型 时,用 auto auto* 没有任何区别,但用 auto 声明引用类型时则必须
&
int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;
    auto& c = x;
    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    *a = 20;
    *b = 30;
     c = 40;
    return 0; 
}
2. 在同一行定义多个变量
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译
器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量
void TestAuto()
{
    auto a = 1, b = 2; 
    auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

7.3 auto雷点

1. auto 不能作为函数的参数
// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}
2. auto 不能直接用来声明数组
void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值