cpp学习中
为什么会有引用,另外引用怎么用:
struct Demo { char name[10000]; int count; }; int main() { Demo my_demo = {0}; Demo *my_demo_p = &my_demo; Demo &my_demo_ref = my_demo; // 方式1:传递实参 func1(my_demo); // 方式2:传递指针 func2(my_demo_p); // 方式3:传递引用 func3(my_demo_ref); return 0; } 如上所示,参数传递可以有三种方式,则三种函数可以这样定义: // 方式1:传递实参 void func1(Demo demo) { cout << demo.name; } // 方式2:传递指针 void func2(const Demo *demo_p) { cout << demo->name; } // 方式3:传递引用 void func3(const Demo &demo_ref) { cout << demo.name; }
可以看出,引用和实参的使用方式很像,但注意以下几点:
从内存使用的角度来说,传递实参,则会将数据拷贝过去(创建了副本),即 func1 对传入的数据做任何修改,都不会影响 my_demo。
既然传递实参要创建副本,就意味着效率更低。例子中结构体的 name 成员长度为 10000,就是要突出这个效率问题。
引用和指针也很像,它们都不会创建副本,因此效率都很高。它们的主要区别在于:
选择成员的时候,引用使用点 . 来查找,而指针则使用 -> 来查找。
指针可能传递一个 NULL 过来,因此在使用前必须检查有效性;引用则必然代表某个对象,不需要做此检查。
PS: 在代码中加上 const 关键字的目的,是不希望 func2 和 func3 去修改原始数据,因为函数仅仅是为了打印出 name。
(1)以引用返回函数值,定义函数时需要在函数名前加 &
(2)用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。
引用作为返回值,必须遵守以下规则:
(1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
(2)不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
(3)可以返回类成员的引用,但最好是const。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常 量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。