1、援用的意义
援用作为变量别号
而存在,因而在一些场所能够替换指针,援用相对于指针来讲具有更好的可读性和实用性
// swap函数的完成对照 void swap(int& a, int& b) { int t = a; a = b; b = t; } void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; }
注重:函数中的援用形参不须要举行初始化,初始化是在挪用的时刻完成的
2、特别的援用
const援用
在C++中能够声明const
援用,细致用法以下:
const Type& name = var;
const
援用让变量具有只读属性,这个只读属性是针对当前的这个别号,变量是能够经由历程别的体式格局举行修正
int a = 4; // a是一个变量 const int & b = a; // b是a的一个援用,然则b具有只读属性 int * p = (int *)&b; // p = &a b = 5; // err, 援用b 被const润饰,b是一个只读变量 a = 6; // ok printf("a = %d\n", a); *p = 5; // ok printf("a = %d\n", a);
当运用常量对const
援用举行初始化时,C++编译器会为常量值分派空间,并将援用名作为这段空间的别号
#include <stdio.h> void Example() { printf("Example:\n"); int a = 4; const int& b = a; int* p = (int*)&b; //b = 5; // b *p = 5; printf("a = %d\n", a); printf("b = %d\n", b); } void Demo() { printf("Demo:\n"); const int& c = 1; int* p = (int*)&c; //c = 5; *p = 5; printf("c = %d\n", c); } int main(int argc, char *argv[]) { Example(); printf("\n"); Demo(); return 0; }
结论:运用常量对
const
援用初始化后将发生一个只读变量
题目:援用有自身的存储空间吗?
struct TRef { char& r; } printf("sizeof(TRef) = %d\n, sizeof(TRef));
考证顺序:
#include <stdio.h> struct TRef { char& r; // 字符范例援用 }; int main(int argc, char *argv[]) { char c = 'c'; char & rc = c; TRef ref = { c }; // 用C举行初始化, TRef.r 就是 c的别号了 printf("sizeof(char&) = %d\n", sizeof(char&)); // char援用的大小,援用即变量自身,求所对应的变量自身的大小,即sizeof(char) = 1 printf("sizeof(rc) = %d\n", sizeof(rc)); // rc是一个援用,即sizeof(c) = 1 printf("sizeof(TRef) = %d\n", sizeof(TRef)); // sizeof(TRef) = 4 printf("sizeof(ref.r) = %d\n", sizeof(ref.r)); // TRef.r是 c的别号,sizeof(c) = 1 // sizeof(TRef) = 4 // 指针变量自身也是占4个字节 // 援用和指针的关联 return 0; }
3、援用的实质
援用在C++中的内部完成是一个指针常量
注重:
1、C++编译器在编译历程顶用 指针常量 作为援用的内部完成,因而援用所占用的空间大小于指针雷同
2、从运用的角度,援用只是一个别号,C++为了运用性而隐蔽了援用的存储空间这一细节。
#include <stdio.h> struct TRef { char* before; // 4字节 char& ref; // 4字节 char* after; // 4字节 }; int main(int argc, char* argv[]) { char a = 'a'; char& b = a; char c = 'c'; TRef r = {&a, b, &c}; printf("sizeof(r) = %d\n", sizeof(r)); // sizeof(r) = 12 printf("sizeof(r.before) = %d\n", sizeof(r.before)); // sizeof(r.before) = 4 printf("sizeof(r.after) = %d\n", sizeof(r.after)); // sizeof(r.after) = 4 printf("&r.before = %p\n", &r.before); // &r.before = 0xbuf8a300c printf("&r.after = %p\n", &r.after); // &r.after = 0xbuf8a3014 /* 0xbuf8a3014 - 0xbuf8a300c = 8 before占了4个字节,所以ref也是占4个字节 */ return 0; }
援用的意义:
C++中的援用旨在大多半的情况下替换指针
功能性:能够满足多半须要运用指针的场所
安全性:能够避开因为指针操纵不当带来的内存毛病
操纵性:简朴易用,又不失功能强大
然则
援用能够在大多半情况下防止内存的毛病,函数返回局部变量的援用,就没法防止了
#include <stdio.h> int& demo() { int d = 0; printf("demo: d = %d\n", d); return d; // 实际上是返回了局部变量的地点,局部变量函数完毕就销毁了,返回毛病 } int& func() { static int s = 0; printf("func: s = %d\n", s); return s; // 返回静态局部变量的地点,静态局部变量存储在全局区,函数完毕生命周期还在,返回胜利 } int main(int argc, char* argv[]) { int& rd = demo(); // rd 成为demo内里返回的局部变量d的别号,涌现正告,然则经由历程编译 int& rs = func(); // rs 成为静态局部变量 s 的别号 printf("\n"); printf("main: rd = %d\n", rd); // rd = 13209588,rd代表的是一个不存在的变量,现在是一个野指针 printf("main: rs = %d\n", rs); // rs = 0 printf("\n"); rd = 10; rs = 11; // 经由历程rs改变了静态局部变量s的值 demo(); // d = 10 func(); // s = 11 printf("\n"); printf("main: rd = %d\n", rd); // rd = 13209588 printf("main: rs = %d\n", rs); // rs = 11 printf("\n"); return 0; }
4、小结
援用作为变量别号而存在旨在替代指针
const
援用能够使得变量具有只读属性援用在编译器内部运用指针常量完成
援用的终究实质为指针
援用能够尽量地避开内存毛病
相干文章:
php的轮回与援用的一个坑,php轮回援用
双引号的用法 PHP 单引号与双引号的区分
以上就是C++援用的意义与援用的实质的细致内容,更多请关注ki4网别的相干文章!