C++基本概念

一、基本概念

1.常量
在C++中我们使用const定义常量,在定义常量时,const可以位于类型之前,也可以位于类型与常量标识符之间。
如:

const double cd_pi=3.14159;

double const cd_pi=3.14159;

注意:在C++中,常量不允许被修改,而且必须在被定义时初始化。

常量指针

常量指针必须初始化,而且初始化以后就无法改变其存储的地址值。

int i=2;
int *const j=&i;//常量指针
const int h=3;
const int *const k=&h;//指向常量的常量指针

顶层const:自身不可被改变
底层const:自身所指对象不可被改变
const默认作用左边的东西,否则作用于右边的东西

2.引用:引用是一个具体对象的别名。引用就是其关联实体的另外一个名字,对引用的操作就是对其关联实体的操作。

int a=30;
int b;
int &ra=a;
int &rb=b;

*引用与指针的不同点:引用只是关联实体的另一个名字,不会产生新的实体,并且引用在定义时就确定了与关联的实体对象,这种关系是不可改变的,直至引用灭亡。

使用引用的注意事项:

(1)引用的类型必须与其关联对象的类型一致。
(2)引用在定义时就必须初始化,确定引用与关联实体的关系。
(3)给引用初始化的必须是一个内存实体,可以是变量也可以是常量,由于引用本身不是一个对象因此不能定义引用的引用。

指向指针的引用
int *p;//p是一个int型指针
int *&m=p;//r是一个对指针的引用
对常量的引用

初始化常量引用时允许使用任意表达式作为初始值,只要该初始值结果能够转化为引用的类型即可。
因此,常量引用的对象可以是非常量、字面值、甚至是表达式。

int i=42;
const int &a=i;//正确
const int &b=i*2;//正确

下面所示程序中将常量整型j绑定在双精度浮点数i上,其中编译器做了一个类型装换。

double i=3.14;
const int &j=i;
const int temp=i;
const int &j=temp;

实际上常量引用j被绑定在编译器创建的临时量temp上。
但由于在非常量引用时,需要对引用采取赋值操作,因此将该引用绑定在临时量上是无意义的,所以C++将这种行为归为非法。

3.函数

(1)函数定义

C++函数可分为两类:标准库函数和用户自定义函数。
用户自定义函数定义形式如下:

返回值类型 函数名(<形式参数列表>){
     
     // 函数代码
}

形式参数列表中的形式参数成为形参,是函数与其他函数传输数据的通道。

(2)函数调用
函数名(<实参列表>)
(3)参数传递
程序运行时的内存布局

一般而言,操作系统将程序装入内存后,就形成一个随时可以运行的进程空间,该进程空间可分为四个区域。

代码区
全局数据区
堆区
栈区

代码区:存放程序的执行代码,由函数定义块编译生成。
全局数据区:存放程序中的所有全局数据、常量、文字量、静态全局变量、静态局部变量。
堆区:存放程序中产生的动态内存,供程序随机申请使用。
如果程序中反复申请动态内存,且没有在适当时机释放,则会慢慢将程序的整个堆区占有,导致程序崩溃,这就是常说的内存泄漏
栈区:存放函数数据(即局部数据),其动态反映了程序运行中的函数状态。

C++中有两种形式的函数参数传递,分别是传值形式和传地址形式

无论哪种参数传递形式,函数的参数传递永远是从实参到形参的单向传递
传值形式:在传值形式中,实参值被复制到对应的形参对象中,作为形参的初始值。系统只有在函数调用时才在栈区给形参分配空间。函数中对形参的访问、修改都是在形参对象上完成的,不会对实参值有热河影响。
传地址形式
显然函数参数的传值形式无法在函数中操作实参,无法操作主调函数的数据。因此只能通过传地址形式

指针传递:

指针作为函数形参时,实参到形参的传递是将主调函数的数据地址传递给形参,从而被调函数通过形参具有操作主调函数数据的能力。

引用传递:

引用参数的效果与指针参数的效果一样,引用参数的表现形式与指针参数完全不同,引用参数的形参为引用,在函数调用时实参为对象名,形式上与传值形式相同。

(4)函数重载

C++编译器能够根据函数参数类型、数量或排列顺序的差异来区分同名函数,这种技术成为重载技术,相应的同名函数称为重载函数
判定两个或多个同名函数是否为重载函数的基本原则:
(1)函数的参数个数不同
(2)函数的参数类型不同
(3)函数的参数顺序不同
注意:函数的返回值类型不能作为区分同名函数的条件,因为匹配函数时值根据参数来匹配函数,而不关注函数的返回值。

(5)带有默认参数值的函数

C++允许在函数声明中为参数给定默认值,在调用函数时,编译器按照从左向右的书序将实参与形参匹配,若为指定足够的实参,则编译器对未分配的形参使用函数声明中给定的默认值。
函数参数设置默认值必须遵循以下规则:
(1)默认参数值只能在函数声明中设定,只有当程序中每有函数声明,默认值参可以在函数定义的头部设定。
(2)设定函数的默认参数值时必须按照从右到左的顺序设定。
4.命名空间:用一个集合名称表示程序中一组名称项的方法。
例:
这里定义了命名空间myspace,其中定义了全局变量gitcount以及函数print_info。

namespace myspace{
     
int gitcount;  //全局计算器
void print_info(char *pstring);
}

命名空间有三种使用方法:
(1)在使用命名空间中的变量或函数时,指明该变量或函数的命名空间作用域。

int count =myspace::gitcount;

(2)在程序中显式声明命名空间的变量或函数,这样在使用这些变量与函数时就与在使用相同作用域的标识符一样。

using namespace myspace::gitcount;
int count=gitcount;

(3)
在程序中显示声明整个名字空间,导致名字冲突问题扩展到了两个名字空间作用域内,命名空间对标识符冲突失去了作用。

namespace myspcae2{
     
using namespace myspace;
int ginum;   //不能与myspace中标识符名字相同,否则会引起标识符冲突问题
void myprint(char *pstring);
}

std是C++标准库的命名空间,通常要在程序中声明命名空间std。

use namespace std;

5.运算符
条件运算符 ? :

Exp1?Exp2:Exp3;

若Exp1为真 ,则该式取Exp2的值;若Exp1为假,则该式取Exp3的值。
6.常量表达式
常量表达式是指值不会改变并且在编译过程就已经能得到结果的表达式。
一个对象(表达式)是不是常量表达式由数据类型和初始值共同决定。

const int i=4;//i是常量表达式
const int j=i+1;//j是常量表达式
int k=4;//k不是常量表达式,因为k的数据类型不是常量
const int m=get_size();//m要到程序运行时才能达到结果,所以不是常量表达式

constexpr变量
声明为constexpr的变量一定为常量且必须用常量表达式初始化。

constexpr int i=4;
constexpr int j=i+1;
字面值类型

由于常量表达式必须在编译时就得到结果,因此constexpr所用到的数据类型必须有所限制,这些能被constexpr声明的类型称为字面值类型。算术类型、指针、引用都属于字面值类型。
一个constexpr的初始值
7.类型别名
类型别名是一个名字。它是某种类型的同义词。
有两种方法用于定义类型别名。
1)、关键字typedef

typedef double wages;//wages是double的同义词

2)、别名声明

using uzi=int;
uzi god=1;

注意

typedef char *pstring;
const pstring cstr=0;//cstr是指向char的常量指针
const pstring *ps;//ps是一个指针,它的对象是指向char的常量指针

8.auto类型说明符
auto能够自动分析表达式的值得数据类型。

int j=0,k=0;
auto i=j+k;

auto 会忽略顶层const,保留底层const。

const int i=0,&ci=i;
auto h=&ci;//h的数据类型是const int*是指向常量整型的指针

9.decltype类型指示符
decltype选择并返回操作数的数据类型

decltype(f()) sum=x;//sum的类型函数f的返回类型

decltype 与引用
当decltype((variable))的结果永远是引用,而decltype(variable)只有当变量是引用时结果才是引用。

你可能感兴趣的:(C++基本概念)