C++入门(二)

一、引用

1、概念

        引用不是定义一个变量,而是给以恶搞已有成员起一个别名,编译器不会为引用变量开辟内存空间,应用变量与被引用变量共用同一块空间。

int main()
{
    int a=10;
    int &b=a;
    cout<<&a<<endl;
    cout<<&b<<endl;
    return 0;
}

这段代码执行的结果是相同的,说明引用的地址不会改变。

2、引用特性

        1、引用在定义时必须初始化

        2、一个变量可以有多个引用

        3、一个引用只能对应一个变量,不可以作为其他变量的别名

int main()
{
    int a=10;
    int& b=a;
    int& c=a;
    int d=0;
    //int& c=d;由于c已经是a的引用了,c不可以再作为d的引用 
    //int& e;引用必须要初始化
    return 0;
}

 三、常引用

在使用引用的过程中,我们只允许权限的平移和缩小,权限放大就会报错

例如一些写使用const修饰的变量

下面是一些例子

int main()
{

    //1、权限的放大
	const int a = 10;
	//int& ra = a; 
	//a是只读的,而ra的权限是可读可写的,如果让ra作为a的别名,就会使对a的权限放大
	const int& ra = a;//权限的平移
	int p = a;//注意:这里并不是权限的放大,只是将m的值拷贝给p,并没有涉及到引用,只是把a赋值给了p,p和a的地址是不一样的
 
    //权限的缩小
	int b = 0;
	const int& rb = b;//权限的缩小,此时不能修改rb,但是可以通过修改b达到修改rb的目的
 
    //权限的放大(这一条与引用无关)
	const int c = 0;
	const int* p1 = &c;
	//int* p2 = p1;这一句是把p2的值赋给p1,但是由于p2是可读可写的,而p1是只读的,权限放大了,所以会报错。

    //权限的缩小(这一条与引用无关) 
	int d = 10;
	int* p3 = &d;
	const int* p4 = p3;

    //常量的引用
	double e = 12.34;
	//double& re1 = 12.34;该语句编译时会出错,对于非常量引用的初始化必须是可修改的变量
	const double& re2 = 12.34;//如果加入const修饰的话,就可以引用初始化为常量
 
    //当类型不同时,涉及到临时变量的问题
	//int& re3 = e;//该语句编译时会出错
	//涉及类型转换时,e不是直接传给re3,而是通过一个临时变量
	//e先把值传给临时变量,临时变量取出整形部分给re3
	//严格来说re3引用的不是e,而是中间产生的临时变量
	//!但是临时变量具有常性,就会产生权限的放大,因此会编译报错
	//注意:double& re1 = e;不会编译报错,因为两者是同类型的,不会产生中间变量
     const int& re4 = e;//这里就不会编译出错
	//临时变量具有常性,会产生权限的放大
	//因此我们可以在前面加上const变成常引用,就不会产生报错
	
    //其他涉及到临时变量的问题
    int x = 0, y = 1;
	//int& r = x + y;//该语句编译报错
	//与上面类似,除了类型转换会产生临时变量
	//如果一个表达式的计算结果没有用变量来接收,这个结果就会放在临时变量中
	//如果计算结果非常小,也可能会直接存放在寄存器中
	//因此r实际上引用的是存放x+y计算结果的临时变量
	//但是临时变量具有常性,就会产生权限的放大,因此会编译报错
	const int& r = x + y;//在前面加上const变成常引用,就不会产生报错
 
	int sum = x + y;
	int& s = sum;
	//通过sum接收表达式的结果,且引用s和sum是同类型的
	//这样就不会产生临时变量,因此也不会报错
}

引用和指针的区别

1、引用是一个变量的别名,指针存储一个变量地址

2、引用在定义时必须初始化,指针没有要求

3、初始化时,引用有了初始化对象后,就不可以更改,而指针则可以修改其指向的对象(同类型的)

4、引用不能为空,但是空(NULL)有指针。

5、sizeof(引用)=引用类型的大小,sizeof(指针)=4/8字节

6、引用自加是引用的对象加一,而指针自加是向后偏移一个类型的大小

7、引用没有多级引用,指针有多级指针。但是引用可以有很多个同级引用,,即一个变量可以有多个别名

8、访问对象的方式不同,指针 需要显式解引用,而引用编译器自己会处理

9、引用比指针使用起来相对安全。(因为没有空引用)

内联函数

概念

        inline修饰的函数叫做内联函数,编译时c++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。内联函数自在减少函数调用的开销,适用于那些函数体少,调用频繁的函数。

        当编译器处理到函数调用时,如果该函数被声明为内联函数,则编译器会尝试将该函数调用替换为函数体内部的代码。当程序运行到函数调用处,会直接执行了函数体内部的代码,就减少了函数调用的消耗。但是并不一定会替换,内联说明只是想编译器发出的一个请求,编译器可以选择忽略这个请求,如果函数体规模过大,就可能会失败。

特性

        inline是一种以空间换取时间的做法。在编译阶段,编译器会用函数体替换函数的调用,这样会使生成的可执行程序变大,但是会减少调用开销,提高程序的运行效率。一般来说,可以将函数体小,不是递归,调用频繁的函数使用inline修饰。

        inline不可以声明和定义分离,否则会导致链接错误。因为内联函数没有地址,在函数调用处会直接展开为函数体内部的代码,因此无法链接。

auto关键字

在早期c/c++中,auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,而在c++11中,标准委员会赋予了auto新的含义:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

可以试一下这段代码感受一下效果。

int Fun()
{
    return 0;
}

int main()
{
    int a=10;
    auto b=a;
    auto c='a';
    auto d=Fun();
    

    cout<<typeid(a).name()<<endl;
    cout<<typeid(b).name()<<endl;
    cout<<typeid(c).name()<<endl;
    cout<<typeid(d).name()<<endl;




}

要注意的是,使用auto定义变量的时候必须进行初始化。

在编译阶段,编译器需要根据初始化的表达式来推到auto的实际类型,因此auto并不是一种类型的声明,而是一个类型声明时的占位符。

用auto声明指针类型的时候,auto与auto*没有区别,用auto声明引用类型的时候必须要加&

int main()
{
    int a = 0;
    auto pa = &a;
    auto* pa1 = &a;
    autp& b = a;

    return 0;
}

基于范围的for循环

用法

for(declaration : range)
{
    //...
}

declaration时范围内用于迭代的变量

range时被迭代的范围

int main()
{
    int array[]={1,2,3,4,5,6};
    for(auto& e : array)
    {
        e *= 2;
    }
    for(auto e : array)
    {
        cout << e <<" ";
    }

}

上面代码中,可以直接用对应的类型声明,也可以用auto。

指针空值nullptr

在c++11以前,指针空值为NULL,但是在传统的c头文件中,NULL实际上是一个宏,被定义为0,因此会出现一些问题。比如我们想要用NULL的类型来作为一些判断条件时,他会被认为时整形,而不是指针类型。

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

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

名亡实存

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值