一、常见的函数的种类
函数是C++语言中最重要的一个技术点,一般来说,学习C++时,先会学习非面向对象的函数,主要分为:全局函数、静态函数和常量函数。然后再学习面向对象编程中的成员函数,当然,成员函数也分成静态成员函数和常函数。
在C++的标准不断推进后,又推出了Lambda函数。也就是很多开发者经常说的闭包。而Lambda表达式,从整体看其实它是一个对象,它能够从其可访问作用域范围内捕获相关的变量。通常来说,Lambda表达式作为与函数类似的对象,其处理方式与函数是一致的。
二、函数的编译处理后的位置
在C++语言中,相对于C语言来说要复杂一些。编译在编译过程中,除了要处理成员函数和非成员函数,还要处理Lambda表达式。不管这些函数是否具有静态或常函数等有限制的条件,其函数体在编译后,会存储在代码段中。这个如果大家有一些编译相关的知识应该都好理解,包括在面试时可能也会问一个C/C++程序运行时内存有几个分区,其中一个就是代码段。
只不过在成员函数中,编译器会生成一个隐藏的this指针,可以用来与其它的类成员进行交互。需要说明的是,类的成员函数只有一份,不会因为生成多个类的对象而有多份的拷贝。这也符合设计原则的精神。但是需要说明的,函数指针本身则是变量,其可以有多个拷贝。也就是说,编译器对成员函数的处理有别于成员变量,它们没有在一起存储即成员函数的多少和大小并不会影响对象的大小。
三、特殊函数的处理
大家都知道,在实际的开发中,存在着一些特殊的函数,如:
1、虚函数
虚函数仍然是成员函数,如果没有特殊的限定符,在编译器编译时仍然会将其与普通成员函数一样存储在代码段中,至少多出的什么虚表之类的,那是另外一回事。
2、Lambda表达式
Lambda表达式亦是如此,它同样被存储在代码段,Lambda表达式有一个注意点是其捕获的变量存储的位置,它与Lambda表达式对象本身存储的位置相关,即Lambda表达式对象在栈上,这些变量就在栈上,在其它位置就在其它位置。所以一般可以这么理解,正常情况下,类似函数性质的代码都可以认为编译器会按同样的规则处理,当然,有没有可能出现特殊情况,得看标准的制定。
3、内联函数
inline函数在编译器处理时,如果不认定可内联,则与普通函数类似。否则,会在调用点生成一个副本代码,这也是被诟病的代码膨胀的原因。
4、成员函数中的静态函数
成员函数中的静态函数可以看做和全局函数一样的处理方式,同样在代码段。
5、成员函数中的常函数
常函数其实和普通函数的编译处理方式是一样的,只是增加了对非mutable变量的禁止修改成员变量(this指针是一个常量指针)。
四、总结
通过上面的分析可以看出来,一般来说,函数是单独处理在代码段中的,特别是针对类对象来说,函数并不会占用其大小(sizeof不体现)。学习一些基本的编译知识,对于理解一些技术点的应用非常有用。它可以让开发者很容易的理解问题的本身,从而能够更好的把知识点串联起来。
在学习中不断完善我们的学习!