有关C++中函数的查漏补缺

有关C++中函数的查漏补缺

函数

函数基础

  • 除了函数名,函数指针也可以使用运算符()运行函数
  • 函数的类型指的是 ( 返回类型 + 形参类型 )
  • 存在于语句块中的对象叫自动对象
  • 在函数里面的对象叫局部对象,定义时不给初值就执行默认初始化(内置类型其值是未定义的,使用会报错,不用会警告)
  • 局部对象定义时加个static就成局部静态变量了,不给初始值会执行值初始化(内置类型默认为0)
  • 函数的声明又叫函数原型

参数传递

  • 传实参不用类型一模一样,能转换就行

  • 可以传递数组(传的是首元素指针,所以形参的大小写不写无所谓)或函数(会转换为函数指针)

  • 数组的引用作为形参,则必须指定大小了,而且传的时候也不能乱传了

  • 有的类型不支持拷贝(比如IO),也就不能传值,所以只能传引用

  • 对于形参为const的情况,实参不const也行,但是函数里就别想改值了

  • 对于形参为const 引用的情况,使用引用只是为了避免拷贝的开销,仍然不可以更改值

  • 如果指针是底层const的也就是它是指向const值的指针,那么则不可以通过指针的方式来改,但是实际上是可以改的

  • const的引用或指针形参会导致可接受参数范围的缩小,因为编译器不允许将真的不能改的东西传到可以改的地方

  • 处理不同数量实参,如果类型相同,可以使用initializer_list做形参,类型不同的话则需要写一个可变参数模板

  • initializer_list里的值都是const,并且拷贝赋值操作并不是真的拷贝而是共用,相当于一个vector,有size,也有beginend(不是迭代器而是指针),传实参的时候,实参要用大括号括起来

  • ...也可以用来处理不同数量实参,但一般跟C用,C++中的类传到这种形参一般都拷贝的不对

返回类型

  • 不可以返回数组或函数,必须返回数组或函数的指针或引用
  • 返回void的函数如果返回一个返回void的函数没问题,要是其他值则不行
  • 返回的值只要能隐式转换成函数返回类型就行
  • 返回局部对象的引用或指针很不好,因为函数结束后,这个对象就没了
  • 返回引用类型那么结果就是左值
  • cstdib中的EXIT_SUCCESSEXIT_FAILURE是预处理变量,与机器无关
  • 返回类型是数组指针的时候,不能在声明中忘了维度,维度放在参数列表后面
  • C++11还能返回{}表示的列表,属于骚操作
  • 返回类型太复杂还不想用typedef或者using简化的话 就用尾置返回,也属于骚操作

函数重载

  • 需要注意的是顶层const参数的const会被忽略,所以有无顶层const的两个函数不能算重载,而算重复定义
  • 有无底层const可以算重载,因为确实这样更严格
  • 重载函数的匹配对于实参有优先级的,具体的可以参考书籍,大体规则是精确>const>类型提升>类型转换>类类型转换

函数指针

  • 函数指针指向函数,要求形参和返回类型精确匹配(一模一样,unsigned 和int都不行),加不加&无所谓
  • 当赋予函数指针nullptr或者0时,表示目前不指向任何函数,而不是代表没有类型
  • 函数指针可以作为函数的形参,直接写函数名会自动转为指针
  • 函数指针也能作为返回值,但是返回的时候必须显式指出是指针,这回编译器不给自动转换了
  • 可以使用尾置返回类型来表示返回函数指针,属于骚操作

默认实参

  • 一个作用域中一个形参只能定义一次默认实参,每次声明都可以赋予一个新的没有默认实参的形参,但要保证默认实参都在后面
  • 局部变量当不了默认实参,可以转换为合适类型的表达式可以

内联函数

  • 说白了就是让编译器更快处理,返回类型前加inline就行了,到底联不联交给编译器决定
  • 内联函数可以手动定义多次,因为不手动编译器自己也做了好多次这种定义(因为就是在指定位置替换定义),所以编译器对内联函数比较宽容,但很显然这些定义必须都是一样的,因此最好放在头文件中,constexpr因为是内联函数所以也要遵守这个规则

constexpr函数

  • 返回类型和形参都是字面值类型,而且只有一条return(这样才能保证编译时知道结果),那么这种函数就可以赋给constexpr表达式,因为这都是编译时候干的事,所以constexpr默认设置为内联的
  • 如果不加constexpr那么函数就算生成常量表达式也不会返回常量表达式,因为普通函数就是要运行才知道结果
  • 但是加了constexpr函数可不一定返回常量表达式,当传递非常量,编译时就计算不出值了,也就返回非常量表达式了

assert预处理宏

  • 定义在cassert头文件中,其实也是预处理变量,像一个内联函数,assert(表达式)对表达式求值,一旦为假,就终止程序,真的话就啥也不做,assert干不干活依赖的是NDEBUG这个预处理变量的状态,如果定义了就啥也不做,默认是没定义的
  • assert可不是语法糖,因为只要定义NDEBUG,就真的不干活了,程序就可能会出问题,它只是用来做正式发布后就不做的调试
  • 可以使用NDEBUG#ifndef#endif来创建调试的代码,在命令行输入-D NDEBUG则之间的代码就不运行了
  • C++编译器提供了__func__静态局部变量来输出当前函数的名字, __FILE__ , __LINE__ , __TIME__ , __DATE__分别表示文件名,行数,编译时间,日期,用来为调试输出信息
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 有关C++中函数的查漏补缺