企业网站建设中在方案设计上,淄博住房和城乡建设厅网站,网页制作与设计中string对象,网页模板好的网站好1. 引用
1.1 引用概念 引用不是新定义一个变量#xff0c;而是给已存在变量取了一个别名#xff0c;编译器不会为引用变量开辟内存空间#xff0c;它和它引用的变量共用同一块内存空间。 语法
类型 引用变量名(对象名) 引用实体;
示例
很显然#xff0c;在下面这…1. 引用
1.1 引用概念 引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空间它和它引用的变量共用同一块内存空间。 语法
类型 引用变量名(对象名) 引用实体;
示例
很显然在下面这个例子中a与b共用同一地址。 这里需要注意引用类型必须和引用实体是同种类型的。
1.2 引用特性 1. 引用在定义时必须初始化 2. 一个变量可以有多个引用 3. 引用一旦引用一个实体再不能引用其他实体 示例
引用定义时必须初始化。 一个变量可以多次引用 引用一旦引用一个实体再不能引用其他实体 1.3 常引用 1.权限只能缩小不能放大。 2.类型转换时会产生临时变量临时变量具有常性 关于这两个概念我们结合代码来看详见代码注释 所谓权限无非就是对对象的操作权限对常量我们的操作权限为只读对变量则可读可写。
那么类型转换时会产生临时变量是什么意思呢
我们来看这一段代码
int main()
{double a 13.14;int b a;//double转换为intint i 97;char ch a;if (i ch) //char转换为int{cout 相等 endl;}cout b endl;return 0;
}这一段代码有两个类型转换的例子两者相类似都是在类型转换时产生一个临时变量。 double a 13.14; int b a;中产生一个值为13的临时变量赋值给b。 i与ch的比较中产生一个值为该字符ascll对应值的整型临时变量。 这些临时变量有一个共性那就是具有常性。 1.4 关于引用的使用场景 1.做参数 2.做返回值 1.做参数
我们以下述代码为例曾经的交换数据我们需要借助指针来实现而现在引用就可以而且还比指针简单很多。
引用版
void Swap(int x, int y)
{int temp x;x y;y temp;
}int main()
{int a 10;int b 20;cout a: a \t b: b endl;Swap(a, b);cout a: a \t b: b endl;return 0;
}指针版 明显引用更为方便简洁。
2.做返回值
下面这段代码大家觉得有没有问题呢
int add(int x, int y)
{int c x y;return c;
}
int main()
{int a 10;int b 5;int c 9;int d 10;int ret add(a, b);cout ret:\t ret endl;cout ret:\t ret endl;return 0;
}
我们看看运行结果 很好貌似没有问题但我们发现编译器给我们发出了一个小小的警告如果是以前我们可能会嗤之以鼻不管不顾但现在的我们不一样了一个小小的警告也要抹杀在牢笼里。 完蛋当我们准备解决警告时却发现他是一个大问题。
这个问题我们之前遇到过费了很大的力气才解决掉现在他又出来了。
这是为什么呢 很简单一个函数的生命周期很短函数调用产生函数栈帧函数调用结束函数栈帧销毁。 那函数内产生局部变量或临时变量的生命周期自然随之结束这一段空间就还给了操作系统而我们直接对局部变量起别名并返回然后在其他地方一直使用不就相当于一直在退了房的宾馆里转悠嘛违法行为不可取。 大家不爱看字那就画个图给大家看。 如果你的东西还放在里面宾馆换了个把锁你进不去了东西就丢了。
所以如果是全局变量staic修饰过的变量或者动态开辟的内存就不受限制。
1.5 传值传引用效率比较
我们使用如下代码进行比较两种效率。 ( 关于clock () 的用法大家可以在网上查阅
struct A
{int arr[10000];
};void TestTranVal(A a)//传值
{
}void TestTranQuote(A a)//传引用
{
}
int main()
{A a;size_t begin1 clock();for(int i0;i10000;i)TestTranVal(a);size_t end1 clock();size_t begin2 clock();for (int i 0; i 10000; i)TestTranQuote(a);size_t end2 clock();cout TestTranVal--time:\t end1 - begin1 endl;cout TestTranQuote--time:\t end2 - begin2 endl;return 0;
} 至于为什么会这样且看下面这段文字 以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低。 1.6值和引用的作为返回值类型的性能比较
这里只需要将上面的代码略微改变。
struct A
{int arr[10000];
};A a;//全局变量A TestTranVal()
{return a;
}A TestTranQuote()
{return a;
}
int main()
{size_t begin1 clock();for (int i 0; i 10000; i)TestTranVal();size_t end1 clock();size_t begin2 clock();for (int i 0; i 10000; i)TestTranQuote();size_t end2 clock();cout TestTranVal--time:\t end1 - begin1 endl;cout TestTranQuote--time:\t end2 - begin2 endl;return 0;
} 造成这一现象的原因在1.5后面哦
1.7引用和指针的区别
相信大家在学习引用的时候总是有一种似曾相识的感觉这是因为他的功能和指针有很大部分的重叠。 在语法概念上引用就是一个别名没有独立空间和其引用实体共用同一块空间。 但在底层实现上实际是有空间的因为引用是按照指针方式来实现的。 int main()
{int a 10;int c 9;int b a;b 20;cout a a endl;int* p a;*p 30;cout a a endl;p c;cout *p *p endl;return 0;
} 我们来看看汇编视角的引用与指针 很显然在汇编看来指针与引用并没有区别。
我们试着来总结一下指针与引用的不同点 1.引用是给一个变量起别名而指针存储变量的数据地址。 2.引用在定义时必须初始化指针则没有这个要求。 3.引用定义后就不能再更改指向指针可以这是他们两个最本质的区别也是引用无法完全替代指针的根本原因。 4.在sizeof中引用的结果就是引用类型的大小而指针恒定为4或者8取决于编译器。 5.引用相对于指针更加安全没有空引用但有空指针。 6.譬如自增自减引用操作的是对象的实体内容而指针操作的是地址块。 7.在底层汇编视角引用与指针并没有什么区别。 8.对于对象的访问方式不同指针需要解引用而引用由编译器处理。 2. 内联函数
2.1 概念
以inline修饰的函数叫做内联函数编译时C编译器会在调用内联函数的地方展开没有函数调 用建立栈帧的开销内联函数提升程序运行的效率。 如果在上述函数前增加inline关键字将其改成内联函数在编译期间编译器会用函数体替换函数的 调用。 2.2 内联函数的特性 1. inline是一种以空间换时间的做法如果编译器将函数当成内联函数处理在编译阶段会 用函数体替换函数调用缺陷可能会使目标文件变大优势少了调用开销提高程序运 行效率。 2. inline对于编译器而言只是一个建议不同编译器关于inline实现机制可能不同一般建 议将函数规模较小(即函数不是很长具体没有准确的说法取决于编译器内部实现)、不 是递归、且频繁调用的函数采用inline修饰否则编译器会忽略inline特性 3. inline不建议声明和定义分离分离会导致链接错误。因为inline被展开就没有函数地址 了链接就会找不到 2.3 内联函数与宏
宏的优缺点 优点 1.增强代码的复用性。 2.提高性能。 缺点 1.不方便调试宏。因为预编译阶段进行了替换 2.导致代码可读性差可维护性差容易误用。 3.没有类型安全的检查 。 C有哪些技术替代宏 1. 常量定义 换用const enum 2. 短小函数定义 换用内联函数 结语 指舞键盘上悠然博弈回。如果您感兴趣不妨看看我其他的文章也许会有更多的收获。希望我们能在未来的日子里一起成长共同进步。