第二课
1,背景
1,在c++中,初始化与赋值并不是同一个概念;
2,初始化:创建变量时赋予其一个初始值;
3,赋值:把对象(已经创建)的当前值删除,而用一个新值代替;
2,列表初始化
作为C++11新标准的一部分,用花括号来初始化变量得到了全面的应用,(在此之前,只是在初始化数组的时候用到);
形式:
int a={
0};
int a{
0};//这两种方式都可以将变量a初始化为0
局限性:
当对内置类型使用列表初始化时,若初始值存在丢失的风险,编译会报错;
例子:
int a=3.123;//waring :"初始化":从 "double"转换到 "int",可能丢失数据;
int a={
3.123};//error 从 "double"转换到 "int"需要收缩转换
3,直接初始化
在变量的右侧,使用圆括号将变量的初始值包住。
例子: int a(999);//true
注意事项:不能用圆括号给数组初始化;
事例:
char a[5]={
0,1,2,4,5};//true
char a[5]=(0,1,2,4,5);//error 被判断成逗号表达式
4,三目运算符
1,在C语言中,条件表达式只能作左值;
2,C++中条件表达式可以作右值和左值;
int a=9;
int b=8;
int max;
max=a>b?a:b;//C语言和C++都能通过
a>b?a:b =666;//C语言报错 C++通过
解决办法:
//让表达式返回地址,C语言就可以通过
*(a>b?&a:&b)=999;//true
5,new/delete和malloc/free
1,C++提供了new/delete运算符,代替了malloc/free函数,执行效率更高;
new申请内存:
1,指针变量 = new 类型;//申请内存的时候初始化
2,指针变量 = new 类型[size];//申请数组,创建数组的时候不能指定初始值;
delete释放内存:
1,delete 指针变量;//释放单个对象
2,delete[size] 指针变量;//释放数组
具体例子:
普通数据:
int* p=new int(9);//初始化为9
delete p;//释放
p=nullptr;//将其置空
数组:
int* p=new int[5]{
0};//全部初始化为0
delete[5] p;//释放数组
p=nullptr;//将其置空
2,移动语义(提高效率,不用开辟空间两次)
例子:
int* pa=new int(33);
//无需释放,将这个申请到的内存空间,转给其他变量;
//定义另一个同类型的变量
int* py=nullptr;
py=pa;
pa=nullptr;
delete py;//只需释放一次
py=nullptr;
6,引用
1,引用:对某一变量或对象的别名【注意:对引用的操作和对其绑定的变量或对象的操作完全等价】【关键:引用的变量名与被引用的变量名实际上是同一个,相当于一个人的本名和小名】
2,定义:
语法:类型 &引用名=目标变量名;
例子:
void fun(int* n)//在函数内部改变实参的值需要传变量的地址;
{
*n=999;
}
fun(nullptr);//传nullptr会发生中段
C++的另一种方法:
void fun(int& n)
{
n=999;
}
3,注意事项:
·引用必须初始化;
int& a;//error
方法:int b=0;int& a=b;//true
·引用只能被初始化一个对象,不能再指向其他对象;
int a=6,b=9;
int& n=a;
n=b;//只是把b的值赋值给了n,而不是n引用了b;
·如果要引用右值,可以使用常量引用(无法修改)
int& n=999;//error "初始化":无法从 "int"转换为 "int&",非常量引用的初始值必须为左值
const int& n=999;//true
·右值引用 (相当于常量引用,但是可以修改)
int&& n=999;//true
n=9999;//可以修改值
注意:
例子:
void a(int&& b);//右值引用
int n=99;
a((int&&)n);//不符合规范
改为:a(std::move(n));//C++中: std::move()将左值转成右值
**********************************************************
注意:右值引用与移动语义结合
例子:
void t(int*&& d,int*&& s)
{
d=s;//先转移内存空间
s=nullptr;
}
int* pa=new int(33);
//无需释放,将这个申请到的内存空间,转给其他变量;
//定义另一个同类型的变量
int* py=nullptr;
t(std::move(py),std::move(pa));
delete py;//只需释放一次
py=nullptr;
4,引用的用处
·作为函数参数
void fun(int* n)//在函数内部改变实参的值需要传变量的地址;
{
*n=999;
}
fun(nullptr);//传nullptr会发生中段
C++的另一种方法:
void fun(int& n)
{
n=999;
}
//可以用指针的引用替代二级指针
如:int a(int*& p);//可以改变指针的指向;
·作为函数返回值
int& a()
{
int n=99;
return n;//【注意:不要返回局部变量的引用或地址,可以使用静态变量或全局变量替代】
}
int& y=a();
y=777;
5,引用的本质
·引用在C++中,内部实质上是一个常指针:type &name <==> type* const name
·C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同