C++语言特性相关(+模板及特化实现)

目录

左值和右值的区别?左值引用和右值引用的区别,如何将左值转换成右值

std::move() 函数的实现原理

什么是指针?指针的大小及用法?

什么是野指针和悬空指针?

指针和引用的区别?

常量指针和指针常量的区别

函数指针和指针函数的区别

强制类型转换有哪几种?

如何判断结构体是否相等?能否用 memcmp 函数判断结构体相等?

参数传递时,值传递、引用传递、指针传递的区别?

什么是模板?如何实现?

函数模板和类模板的区别?

什么是模板特化?为什么特化?


左值和右值的区别?左值引用和右值引用的区别,如何将左值转换成右值

左值:指表达式结束后依然存在的持久对象。

右值:表达式结束就不再存在的临时对象。

左值和右值的区别:左值持久,右值短暂

右值引用和左值引用的区别:

1、左值引用不能绑定到要转换的表达式、字面常量或返回右值的表达式。右值引用恰好相反,可以绑定到这类表达式,但不能绑定到一个左值上。
2、右值引用必须绑定到右值的引用,通过 && 获得。右值引用只能绑定到一个将要销毁的对象上,因此可以自由地移动其资源。
        std::move 可以将一个左值强制转化为右值,继而可以通过右值引用使用该值,以用于移动语义。

std::move() 函数的实现原理

1、利用引用折叠原理将右值经过 T&& 传递类型保持不变还是右值,而左值经过 T&& 变为普通的左值引用,以保证模板可以传递任意实参,且保持类型不变;
2、然后通过 remove_refrence 移除引用,得到具体的类型 T;
3、最后通过 static_cast<> 进行强制类型转换,返回 T&& 右值引用。

什么是指针?指针的大小及用法?

指针: 指向另外一种类型的复合类型。

指针的大小: 在 64 位计算机中,指针占 8 个字节空间。

指针的用法:

  1. 指向普通对象的指针
  2. 指向常量对象的指针:常量指针
  3. 指向函数的指针:函数指针
  4. 指向对象成员的指针,包括指向对象成员函数的指针和指向对象成员变量的指针。
  5. this 指针:指向类的当前对象的指针常量。

什么是野指针和悬空指针?

悬空指针:

若指针指向一块内存空间,当这块内存空间被释放后,该指针依然指向这块内存空间,此时,称该指针为“悬空指针”。

野指针:

“野指针”是指不确定其指向的指针,未初始化的指针为“野指针”。

指针和引用的区别?

1、指针所指向的内存空间在程序运行过程中可以改变,而引用所绑定的对象一旦绑定就不能改变。(是否可变)
2、指针本身在内存中占有内存空间,引用相当于变量的别名,在内存中不占内存空间。(是否占内存)
3、指针可以为空,但是引用必须绑定对象。(是否可为空)
4、指针可以有多级,但是引用只能一级。(是否能为多级)

常量指针和指针常量的区别

常量指针:
常量指针本质上是个指针,只不过这个指针指向的对象是常量。
特点:const 的位置在指针声明运算符 * 的左侧。只要 const 位于 * 的左侧,无论它在类型名的左边或右边,都表示指向常量的指针。(可以这样理解,* 左侧表示指针指向的对象,该对象为常量,那么该指针为常量指针。)

指针常量:
指针常量的本质上是个常量,只不过这个常量的值是一个指针。
特点:const 位于指针声明操作符右侧,表明该对象本身是一个常量,* 左侧表示该指针指向的类型,即以 * 为分界线,其左侧表示指针指向的类型,右侧表示指针本身的性质。

函数指针和指针函数的区别

指针函数:
指针函数本质是一个函数,只不过该函数的返回值是一个指针。相对于普通函数而言,只是返回值是指针。

函数指针:
函数指针本质是一个指针变量,只不过这个指针指向一个函数。函数指针即指向函数的指针。

强制类型转换有哪几种?

static_cast:用于数据的强制类型转换,强制将一种数据类型转换为另一种数据类型。

用于基本数据类型的转换。
1、用于类层次之间的基类和派生类之间 指针或者引用 的转换(不要求必须包含虚函数,但必须是有相互联系的类),进行上行转换(派生类的指针或引用转换成基类表示)是安全的;进行下行转换(基类的指针或引用转换成派生类表示)由于没有动态类型检查,所以是不安全的,最好用 dynamic_cast 进行下行转换。
2、可以将空指针转化成目标类型的空指针。
3、可以将任何类型的表达式转化成 void 类型。

const_cast:强制去掉常量属性,不能用于去掉变量的常量性,只能用于去除指针或引用的常量性,将常量指针转化为非常量指针或者将常量引用转化为非常量引用(注意:表达式的类型和要转化的类型是相同的)。

reinterpret_cast:改变指针或引用的类型、将指针或引用转换为一个足够长度的整型、将整型转化为指针或引用类型。

dynamic_cast:其他三种都是编译时完成的,动态类型转换是在程序运行时处理的,运行时会进行类型检查。
只能用于带有虚函数的基类或派生类的指针或者引用对象的转换,转换成功返回指向类型的指针或引用,转换失败返回 NULL;不能用于基本数据类型的转换。
在向上进行转换时,即派生类类的指针转换成基类类的指针和 static_cast 效果是一样的,(注意:这里只是改变了指针的类型,指针指向的对象的类型并未发生改变)。

如何判断结构体是否相等?能否用 memcmp 函数判断结构体相等?

        需要重载操作符 == 判断两个结构体是否相等,不能用函数 memcmp 来判断两个结构体是否相等,因为 memcmp 函数是逐个字节进行比较的,而结构体存在内存空间中保存时存在字节对齐,字节对齐时补的字节内容是随机的,会产生垃圾值,所以无法比较。

参数传递时,值传递、引用传递、指针传递的区别?

参数传递的三种方式:

值传递:形参是实参的拷贝,函数对形参的所有操作不会影响实参。
指针传递:本质上是值传递,只不过拷贝的是指针的值,拷贝之后,实参和形参是不同的指针,通过指针可以间接的访问指针所指向的对象,从而可以修改它所指对象的值。
引用传递:当形参是引用类型时,我们说它对应的实参被引用传递。

什么是模板?如何实现?

模板:创建类或者函数的蓝图或者公式,分为函数模板和类模板。
实现方式:模板定义以关键字 template 开始,后跟一个模板参数列表。

1、模板参数列表不能为空;
2、模板类型参数前必须使用关键字 class 或者 typename,在模板参数列表中这两个关键字含义相同,可互换使用。

函数模板:通过定义一个函数模板,可以避免为每一种类型定义一个新函数。

对于函数模板而言,模板类型参数可以用来指定返回类型或函数的参数类型,以及在函数体内用于变量声明或类型转换。
函数模板实例化:当调用一个模板时,编译器用函数实参来推断模板实参,从而使用实参的类型来确定绑定到模板参数的类型。

函数模板和类模板的区别?

实例化方式不同:函数模板实例化由编译程序在处理函数调用时自动完成,类模板实例化需要在程序中显式指定。
默认参数:类模板在模板参数列表中可以有默认参数。
特化:函数模板只能全特化;而类模板可以全特化,也可以偏特化。
调用方式不同:函数模板可以隐式调用,也可以显式调用;类模板只能显式调用。

什么是模板特化?为什么特化?

模板特化的原因:模板并非对任何模板实参都合适、都能实例化,某些情况下,通用模板的定义对特定类型不合适,可能会编译失败,或者得不到正确的结果。因此,当不希望使用模板版本时,可以定义类或者函数模板的一个特例化版本。

模板特化:模板参数在某种特定类型下的具体实现。分为函数模板特化和类模板特

函数模板特化:将函数模板中的全部类型进行特例化,称为函数模板特化。
类模板特化:将类模板中的部分或全部类型进行特例化,称为类模板特化。
特化分为全特化和偏特化:

全特化:模板中的模板参数全部特例化。
偏特化:模板中的模板参数只确定了一部分,剩余部分需要在编译器编译时确定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值