持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
指针和引用
指针是一个变量,存储的是一个地址,指向内存的一个存储单元;
引用是原变量的一个别名,跟原来的变量实质上是同一个东西。
区别:
- 指针可以在定义的时候不初始化,引用必须在定义的时候初始化
- 指针可以指向NULL,引用不可以为NULL
- 指针初始化之后可以再改变,引用不可以
- 指针和引用都可以作为函数参数,改变实参的值;指针和引用作为函数参数时,指针需要检查是否为空,引用不需要
C++左值和右值
ps:左值--有名字的房子;右值--没有名字的危房
左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。很多人认为它们分别是"left value"、"right value" 的缩写,其实不然。lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 "read value",指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。
一个左值它可能同时具有左值属性和右值属性,左值属性就是它的房子的名字,右值属性就是指住房子的人,也就是对象的值
C++左值引用
ps:给有名字的房子起个别名。
C++引用,使用 "&" 表示。但此种引用方式有一个缺陷,即正常情况下只能操作 C++ 中的左值,无法对右值添加引用
int num = 10;
int &b = num; //正确
int &b;//错误
int &b = 10; //错误
不支持为右值建立非常量左值引用,但允许使用常量左值引用操作右值。也就是说,常量左值引用既可以操作左值,也可以操作右值
int num = 10;
const int &b = num;
const int &c = 10;
我们知道,右值往往是没有名称的,因此要使用它只能借助引用的方式。这就产生一个问题,实际开发中我们可能需要对右值进行修改(实现移动语义时就需要),显然左值引用的方式是行不通的。
C++右值引用
ps:给没有名字的危房起名字
C++11 标准新引入了另一种引用方式,称为右值引用,用 "&&" 表示。需要注意的,和声明左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右值进行初始化
int num = 10;
//int && a = num; //右值引用不能初始化为左值
int && a = 10;
和常量左值引用不同的是,右值引用还可以对右值进行修改
int && a = 10;
a = 100;
cout << a << endl;
i++ vs ++i
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
int i = 10;
int& j = (++i);
cout<<i<<" "<<&i<<endl;
cout<<j<<" "<<&j<<endl;
return 0;
}
/*
11 0x6ffe14
11 0x6ffe14
*/
++i先加后用,返回的是原来的房子,左值
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
int i = 10;
int &&j = (i++);
cout<<i<<" "<<&i<<endl;
cout<<j<<" "<<&j<<endl;
return 0;
}
/*
11 0x7fff97cbc1c8
10 0x7fff97cbc1cc
*/
i++先用后加,返回临时对象,右值
具体用哪个,i++的效率会低一点,因为它产生了临时变量,临时变量的产生和销毁都需要花时间。