爱未来企业邮箱,突唯阿网站seo,南沙哪有做网站的,网站建设报价是多少目录
6.引用
6.1引用概念
6.2引用的写法
6.3引用的特性
6.4常引用
6.5引用的使用场景
6.5.1引用做参数
6.5.2引用做返回值❗❗
#x1f387;值做返回值
#x1f387;引用做返回值
#x1f387;引用在顺序表做返回值
6.5.3传值、传引用效率比较(参数#xff0…目录
6.引用
6.1引用概念
6.2引用的写法
6.3引用的特性
6.4常引用
6.5引用的使用场景
6.5.1引用做参数
6.5.2引用做返回值❗❗
值做返回值
引用做返回值
引用在顺序表做返回值
6.5.3传值、传引用效率比较(参数
6.5.4值和引用的作为返回值类型的性能比较返回值
6.6引用和指针
6.6.1引用替换指针的场景
6.6.2引用和指针的区别 6.引用
6.1引用概念 引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空 间它和它引用的变量共用同一块内存空间。引用就是别名。引用类型 比如李逵在家称为铁牛江湖上人称黑旋风。 6.2引用的写法 引用的写法格式 类型 引用变量名(对象名) 引用实体可以给变量的别名取别名所有别名都是公用同一块内存空间。注意引用类型必须和引用实体是同种类型的 //类型 引用变量名(对象名) 引用实体;
void TestRef()
{int a 10;int ra a;//定义引用类型printf(%p\n, a);printf(%p\n, ra);
}【验证变量和变量的引用别名是否是同一块内存空间】
#includeiostream
using namespace std;int main()
{int a 0;int b a;int c a;cout a endl;cout b endl;cout c endl;cout b endl;cout c endl;b;//b的同时a了吗c了吗cout a endl;cout b endl;cout c endl;return 0;
} 【别名的别名类型一致原则】
int main()
{int a 0;int b a;int c b;cout a endl;cout b endl;cout c endl;//❌double ba;类型必须一致return 0;
} 6.3引用的特性 1. 引用在定义时必须初始化2. 一个变量可以有多个引用 3. 引用一旦引用一个实体再不能引用其他实体 大家可以自己动手验证下。 int main()
{int a 0;//1.引用必须初始化//int b;//b a;//2.引用定义后不能改变指向int b a;int c 2;b c;//这是不是改变指向而是赋值cout a endl;//2cout b endl;//2//3.一个变量可以有多个引用多个别名//定义别名的别名int x a;int d c;return 0;
}
6.4常引用
void TestConstRef()
{const int a 10;//int ra a; // 该语句编译时会出错a为常量const int ra a;// int b 10; // 该语句编译时会出错b为常量const int b 10;double d 12.34;//int rd d; // 该语句编译时会出错类型不同const int rd d;
}
6.5引用的使用场景
6.5.1引用做参数 引用做参数 输出型参数输入型参数对象比较大减少拷贝提高效率指针可以做但是引用的更方便更有性价比 //输出型参数
int* preorderTraversal(struct TreeNode* root, int* returnSize)
int* preorderTraversal(struct TreeNode* root, int returnSize) //交换两个变量#includeiostream
using namespace std;void Swap(int* p1, int* p2)
{int tmp *p1;*p1 *p2;*p2 tmp;
}
int main()
{int x 10;int y 20;cout x x endl;cout y y endl;Swap(x, y);cout x x endl;cout y y endl;return 0;
}void Swap(int p1, int p2)
{int tmp p1;p1 p2;p2 tmp;
}
int main()
{int x 10;int y 20;cout x x endl;cout y y endl;Swap(x, y);cout x x endl;cout y y endl;return 0;
}
//不能交换地址 6.5.2引用做返回值❗❗
值做返回值 请问return a意味着把a的值传给func吗回顾函数栈帧的创建与销毁-CSDN博客 函数调用结束函数栈帧就销毁了return需要返回值会再函数栈帧销毁之前拷贝放到临时空间里面。给ret接收。 数据小临时空间是寄存器。数据大。 #includeiostream
using namespace std;
int func()
{int a 0;return a;
}int main()
{int ret func();return 0;
}引用做返回值 函数调用结束函数栈帧就销毁了return返回a的别名给ret接收。 ret接收到了之后后面访问a的别名也就是访问a的空间但是a的空间已被销毁就会造成非法访问野引用的问题。非法访问特别注意 如果a的内存空间在函数调用之后没有被清理去访问可能访问到原值。但是如果后序定义其他的变量这个内存位置可能就被操作系统分配给其他的变量。如果a的内存空间在函数调用之后被清理了访问到了随机值。 注意如果函数返回时出了函数作用域如果返回对象还在(还没还给系统)则可以使用引用返回如果已经还给系统了则必须使用传值返回。返回变量出了函数作用域就生命周期局部变量不能用引用返回。返回变量出了函数作用域就生命周期到了就销毁不能用引用返回。非法访问野引用对程序存在安全隐患。C中临时变量具有常量不可被修改 全局变量/静态变量static/堆上变量等就可以引用做返回值。 【示例一】
#includeiostream
using namespace std;
int func()
{int a 0;//✔static int a0;return a;
}int main()
{int ret func();return 0;
}【示例二】
int Add(int a, int b)
{int c a b;return c;
}
int main()
{int ret Add(1, 2);Add(3, 4);cout Add(1, 2) is : ret endl;return 0;
} 引用在顺序表做返回值 不需要typedef 就可以直接使用SeqList结构体类中可以包含成员函数域不同不用再区分名称开辟的空间在堆上出了作用域函数栈帧没有销毁可以用引用做返回值 返回引用 引用具有了读写双重功能引用中间没有产生临时变量 引用做返回值 修改返回对象减少拷贝提高效率 这个部分到后面还会细讲 //C
#includeiostream
#includeassert.h
using namespace std;
struct SeqList
{//成员变量int* a;int size;int capacity;//成员函数void Init(){a (int*)malloc(sizeof(int) * 4);// ...size 0;capacity 4;}void PushBack(int x){//... 扩容a[size] x;}//读写返回变量int Get(int pos){assert(pos 0);assert(pos size);return a[pos];}int operator[](int pos){assert(pos 0);assert(pos size);return a[pos];}
};int main()
{SeqList s;s.Init();s.PushBack(1);s.PushBack(2);s.PushBack(3);s.PushBack(4);for (int i 0; i s.size; i){//cout s.Get(i) ;cout s[i] ;//cout s.operator[](i) ;}cout endl;for (int i 0; i s.size; i){/*if (s.Get(i) % 2 0){s.Get(i) * 2;}*/if (s[i] % 2 0){s[i] * 2;}}cout endl;for (int i 0; i s.size; i){cout s.Get(i) ;}cout endl;return 0;
} 6.5.3传值、传引用效率比较(参数 以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低。 clock只能计算出整数位。0ms表示小于1ms不代表没有代表时间极其短。 #include time.h
struct A { int a[10000]; };
void TestFunc1(A a) {}
void TestFunc2(A a) {}
void main()
{A a;// 以值作为函数参数size_t begin1 clock();for (size_t i 0; i 10000; i)TestFunc1(a);size_t end1 clock();// 以引用作为函数参数size_t begin2 clock();for (size_t i 0; i 10000; i)TestFunc2(a);size_t end2 clock();// 分别计算两个函数运行结束后的时间cout TestFunc1(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl;
} 6.5.4值和引用的作为返回值类型的性能比较返回值 通过上述下述代码的比较发现传值和指针在作为传参以及返回值类型上效率相差很大。 #include time.h
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A TestFunc2() { return a; }
void main()
{// 以值作为函数的返回值类型size_t begin1 clock();for (size_t i 0; i 100000; i)TestFunc1();size_t end1 clock();// 以引用作为函数的返回值类型size_t begin2 clock();for (size_t i 0; i 100000; i)TestFunc2();size_t end2 clock();// 计算两个函数运算完成之后的时间cout TestFunc1 time: end1 - begin1 endl;cout TestFunc2 time: end2 - begin2 endl;
} 6.6引用和指针
6.6.1引用替换指针的场景 指针和引用的功能是类似的重叠的。C的引用对指针使用比较复杂的场景进行一些替换【场景替换】让代码更简单易懂但是不能完全替代指针。C的引用不能完全替代指针的元婴就有引用定义之后不能改变指向但是指针可以改变指向。在Java python 等其他语言里没有指正只有引用且其他语言的引用是可以改变指向的实现链表等。注意区别C的引用是不能改变指向的。C中90%的场景还是使用引用但是在一些特殊场景我们还是使用指针。例如链表二叉树指向一段动态内存开辟的空间 【链表中二级指针】
//双向无头链表
typedef struct Node
{struct Node* next;struct Node* prev;int val;
}LNode,*PNode;//void PushBack(PNode* phead, int x)
void PushBack(PNode phead, int x)
{//
}
int main()
{PNode pphead;PushBack(pphead, 1);
}
【输出型参数】 OJ输入型参数直接给数据使用。 OJ输出型参数给参数需要修改这个参数指针/别名 int* preorderTraversal(struct TreeNode* root, int* returnSize)
int* preorderTraversal(struct TreeNode* root, int returnSize) 6.6.2引用和指针的区别 引用和指针的不同点: 1. 引用概念上定义一个变量的别名指针存储一个变量地址。2. 引用在定义时必须初始化指针没有要求。3. 引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何一个同类型实体。4. 没有NULL引用但有NULL指针。5. 在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占4个字节)。6. 引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小。7. 有多级指针但是没有多级引用。8. 访问实体方式不同指针需要显式解引用引用编译器自己处理。9. 引用比指针使用起来相对更安全 。底层是底层语法是语法二者不可混为一谈。 在语法概念上引用就是一个别名没有独立空间和其引用实体共用同一块空间。 int main()
{int a 10;int ra a;cout a a endl;cout ra ra endl;return 0;
} 在底层实现上实际是有空间的因为引用是按照指针方式来实现的。 int main()
{int a 10;int ra a;ra 20;int* pa a;*pa 20;return 0;
} 引用和指针的区别 【语法】 引用是别名不开空间指针是地址需要开空间存地址。引用必须初始化指针可以初始化可以不用初始化。引用不能改变指向指针可以改变指向。引用相对更加安全没有空引用但有空指针。容易出现野指针但不容易出现野引用。其他方面。 【底层】 汇编层面上没有引用只有指针引用编译后也转换成指针了。 感谢大家的阅读若有错误和不足欢迎指正。