C++入门基础

一,目录
1,C++关键字
2,命名空间namespace
3,C++的输入和输出
4,缺省参数
5,函数重载
6,引用
7,内联函数
8,auto关键字
9,基于范围的for循环
10,指针空值-nullptr

二,内容介绍
1.C++关键字
C语言有32个关键字。C++有63个关键字。
在这里插入图片描述
在这里插入图片描述

2.命名空间
1>.作用:对标识符的名称进行本地化,避免命名冲突或名字污染。
2>.定义:定义命名空间,需要使用namespace关键字,后面跟命名空间的名字,然后接一对{ }即可,{ }中即为命名空间的成员。
2.2.1
a.普通的命名空间
命名空间中的内容,既可以定义变量,也可以定义函数
b.命名空间可以嵌套
c.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间。

namespace N1
{
 //命名空间中的内容,可以定义变量,也可以定义函数
 int a; 
 int Add(int left, int right)
 {
  return left + right;
 }
}
//2.命名空间可以嵌套
namespace N2
{
 int a;
 int b;
 int Add(int left, int right)
 {
  return left + right;
 }
}
namespace N3
{
 int c;
 int d;
 int sub(int left, int right)
 {
  return left - right;
 }
}
//3.同一个工程中允许存在多个命名空间
//编译器最后会合成同一个命名空间。
namespace N1
{
 int Mul(int left, int right)
 {
  return left * right;
 }
}

注意:一个命名空间就定义了一个新的作用域,命名空间中所有的内容都局限于该命名空间。
3>使用
a.加命名空间名称及作用域限定符。
b.使用using将命名空间中的成员引用。
c.使用using namespace 命名空间名称使用

a.加命名空间名称及作用域限定符。
int main()
{
 printf("%d\n", N::a);
 }

b.使用using将命名空间中的成员引用。
using N::b;
int main()
{
 printf("%d\n", N::a);
 printf("%d\n", b);
 return 0;
}

c.使用using  namespace 命名空间名称使用
using namespace N;
int main()
{
 printf("%d\n", N::a);
 printf("%d\n", b);
 Add(10, 20);
 return 0;
}

3**.C++输入&输出**
1.使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含头文件以及std标准命名空间。
2.使用C++输入输出方便,不需增加数据格式控制。比如:%d,%c

#include<iostream>
using namespace std;
int main()
{
 int a;
 double b;
 char c;
 cin >> a;
 cin >> b >> c;
 
 cout << a << endl;
 cout << b << " " << c << endl;
 return 0;
}
#if 0

4.缺省参数
4.1概念:缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的参数。
4.2类型:
全缺省参数void TestFunc(int a = 0,int b=20,int c=30)
半缺省参数void TestFunc(int a, int b = 10, int c = 20)

void TestFunc(int a = 0,int b=20,int c=30)//全缺省参数
{
 cout <<"a="<<a<< endl;
 cout << "b=" << b << endl;
 cout << "c=" << c << endl;
}

//半缺省参数必须从右往左一次给出,不能间隔着给。
void TestFunc(int a, int b = 10, int c = 20)//半缺省参数
{
 cout << "a=" << a << endl;
 cout << "b=" << b << endl;
 cout << "c=" << c << endl;
}

注意:1.半缺省参数必须从右往左一次给出,不能间隔着给。
2.缺省参数不能在函数声明和定义中同时出现。
3.缺省值必须是常量或者全局变量。
4.C语言不支持(编译器不支持)。

//同名的无参函数和全缺省函数不能同时存在
void TestFunc(int a = 10)
{}
void TestFunc()
{}
int main()
{
 TestFunc();
 return 0;
}

5.函数重载
1.概念:c++允许同意在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或顺序)必然不同,常用来处理实现功能类似数据类型不同的问题。

//函数重载:必须在相同的作用域,函数名字必须相同,参数列表(个数,类型,类型顺序)不同
int Add(int left, int right)
{
 return left + right;
}
double Add(double left, double right)
{
 return left + right;
}
//int  Add(double left, double right)
//{
// return left + right;
//}//如果两个函数仅仅是返回值不同,不能构成函数重载
int main()
{
 //编译器在编译阶段,根据对所传递实参类型的推演,根据推演实际结果选择调用
 Add(10, 20);
 Add(10.0, 20.0);
 Add(1, (int)2.3);//对实参进行隐式类型转化
 return 0;
}

2.名字修饰
概念:是一种在编译过程中,将函数,变量的名称重新改编的机制,简单来说就是编译器为了区分各个函数,将函数通过某种算法,重新修饰为一个全局唯一的名称。
注意:C语言不支持函数重载
原因:C语言编译器对函数名字的修饰规则–只是在函数名字前加下划线_。在当前工程中相同函数名函数时,就会冲突。
C++的命名规则:被修饰后的名字中包含了:函数的名字以及参数类型。将参数类型包含在最终的名字中,就可保证名字在底层的全局唯一性。:作用域+返回类型+函数名+参数列表。

既然返回值类型也考虑到映射机制中,这样不同的返回类型映射之后的函数名肯定不一样了,为什么不将函数返回类型考虑到函数重载中?
为了保持解析操作符或函数调用时,独立于上下文(不依赖于上下文)

float sqrt(float);
double sqrt(double);

void f(double da, float fla)
{
      float fl=sqrt(da);//调用sqrt(double)
      double d=sqrt(da);//调用sqrt(double)

    fl=sqrt(fla);//调用sqrt(float)
   d=sqrt(fla);//调用sqrt(float)
}
//如果返回类型考虑到函数重载中,
//这样将不可能再独立于上下文决定调用哪个函数。

3.extern "C"

//#include<stdio.h>
//#include<Windows.h>
//C语言中不支持函数重载
//原因:C语言编译器对函数名字的修饰规则-》只是在函数名前加下划线_
extern "C" int Add(int left, int right);//将函数按照C风格编译
//{
// return left + right;
//}
//double Add(double a, double b);
int main()
{
 Add(1, 3);
 Add(1.0, 3.0);
 return 0;
}

6.引用
1.概念:给已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量公用同一块内存空间。
类型& 引用变量名(对像名)=引用实体;
2.特性
1>引用在定义时必须初始化。
2>一个变量可以有多个引用。
3>引用一旦引用一个实体,再不能引用其他实体。

//引用必须初始化,引用类型必须和引用实体是同种类型
int main()
{
 int a = 10;
 int& ra = a;
 int& rra = a;
 int& rrra = ra;
 rrra = 100;
 return 0;
}```

3.常引用

int main()
{
 const int a = 10;
 const int& ra = a;
 //int& ra = a;//编译错误
 
 const int& b = 100;
 //int& b=100;//错误
 
 double d = 12.34;
 //int& rd = d; // 该语句编译时会出错,类型不同
 //开辟的整形空间rd里面存放数据d的整形部分12,这个空间没有名字,无法对它进行改动,具有常量的性质
 const int &rd = d;
 d = 56.78;
 return 0;
}```

4.应用场景
1.做参数
普通类型的引用:可以通过形参改变实参
const类型的引用:不想通过形参改变实参
2.做返回值:如果函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。

//引用做函数的参数
void Swap(int& left, int& right)
{
 int tmp = left;
 left = right;
 right = tmp;
}
//引用做返回值
int & TestReturn(int &a)
{
 a += 10;
 return a;
}

5.传值和指针在作为传参以及返回值类型上效率相差很大。
在语法概念上,引用就是一个别名,没有独立空间,和其引用实体公用一块空间。
在底层实现上实际是有空间的,因为指针是按照指针方式来实现的。
6.引用和指针的区别
1.引用在定义时必须初始化,指针没有要求。
2.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体。
3.没有NULL引用,但有NULL指针。
4.在sizeof中含义不同:引用结果为引用类型的大小,但指针始终时地址空间所占的字节数(32位平台下时4字节)。
5.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。
6.有多级指针,但没有多级引用。
7.访问实体方式不同,指针需要显示解引用,引用编译器自己处理。
8.引用比指针使用起来相对安全(指针需要判空)。
7.内联函数
1.概念:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,提升程序运行的效率。
2.特性:
1>inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用内联函数。
2.inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等,编译器优化时会忽略掉内联。
3.inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。(内联函数具有文件域)
宏的优缺点?
优点:1.增强代码的复用性。(方便修改)
2.提高性能。(使用带参的宏定义,既可以完成函数调用的功能,又能避免函数的出栈与入栈操作,减少系统开销)
缺点:1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查。
C++有哪些技术替代宏?
1.常量定义 换用const
2.函数定义使用内联函数
8.auto关键字
1.含义:最开始使用auto修饰的变量,是具有自动存储器的局部变量。
C++11中,新的含义:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推到而得。

int TestAuto()
{
 return 10;
}
int main()
{
 int a = 10;
 auto b = a;
 auto c = 'a';
 auto d = TestAuto();
 //auto e;//无法通过编译,使用auto定义变量时必须对齐进行初始化
 cout << typeid(b).name() << endl;//int
 cout << typeid(c).name() << endl;//char
    cout << typeid(d).name() << endl;//int
 system("pause");
 return 0;
}

注意:使用auto定义变量时必须对其初始化,在编译阶段编译器需要根据初始化表达式来推到auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。
2.使用规则:
1>auto与指针和引用结合起来使用
用auto声明指针类型,用auto和auto*没有任何区别,但是auto声明引用类型时则必须加&。
2>在同一行定义多个变量
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推到,然后用推导出来的类型定义其他变量。
3>auto不能推导的场景

1.auto不能作为函数的参数。
2.auto不能直接用来声明数组。

void TestAuto(auto a)
{}

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

9.基于范围for循环(C++11)
1.范围for循环(for循环后的括号由冒号:分为两个部分:
第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

int main()
{
 int array[] = { 1, 2, 3, 4, 5 };
 //让e引用每一个数组中的元素<加引用>
 for (auto& e : array)
 {
  e *= 2;
 }
 //e就是数组中每个元素的一份拷贝<不加引用,,对e进行修改,不能修改数组中的元素>
 for (auto e : array)
 {
  cout << e << " ";
 }
 system("pause");
 return 0;
}

2.使用条件
1.for循环迭代的范围必须是确定的。
对于数组而言,就是数组中第一个元素和最后一个元素的范围;
对于类而言,应该就是begin和end的方法,begin和end就是for循环迭代的范围。
2.迭代的对象要实现++和==的操作。
10.指针空值nullptr(C++11)
1.C++98中,字面常量0既可以是一个整形的数字,也可以是无类型的指针(void*)常量,但是在编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强制转(void *)()。
2.C++11提供了nullptr,即:nullptr代表一个指针空值常量,nullptr是有类型的,其类型为nullptr_t,仅仅可以被隐式转化为指针类型,nullptr_t被定义在头文件中:

typedef decltype(nullptr) nullptr_t;

注意:1.在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr时C++11作为关键字引用的。
2.在C++中,sizeof(nullptr)与sizeof((void*)0)所占的字节数相同。
3.为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值