return 终止当前正在执行的函数并将控制权返回到调用该函数调用的地方。
return; return expression
无返回值的函数
无返回值的函数一般被定义为void型,在函数结尾可以不加return,函数会隐形返回。return可以用作中断函数使用。
有返回值的函数
有返回值的函数一般不可定义为void,函数返回的类型就是函数定义的类型。编译器会在运行时检查这一语法错误。
返回的值是一个临时的变量,一般是拷贝的,如果返回的是引用,那就是引用的别名,完成返回之后,返回值所占用的空间也随之被释放掉。
不要返回局部变量的引用或者指针,因为在函数结束的时候局部变量失效了,引用指向的是一个空区域。
引用返回左值
调用一个返回引用的函数返回的是左值,也就是说函数在左边,如
char &get(string s,int i)
{
return s[i];
}
main()
{
string s;
get(s,0)='A';
}
在主函数中,函数在等号的左侧,含义是将字符串第一个元素改成字母A。
列表初始化返回值
vectorf() { return {}; }
C++11规定这样是合法的,返回的空vector
主函数返回值
main函数的返回值可以看作是状态指示器,返回0表示执行成果,返回其他值表示执行失败,如果在主函数中不加入返回值,一般会隐式的传递一个0。
返回一个数组指针
因为子函数无法返回数组,因此可以返回指向数组的指针或引用。
辨析
int a[10]; a是含有10个整数的数组 int *p[10]; p是含有10个指针的数组 int (*p)[10]=&a; p是一个指针,指向一个含有10个元素的数组
返回数组指针的函数类型如下
int (*f(int i))[10] string (*f(int i))[10]
含义是f函数将会调用一个大小是10的int型数组,并且返回类型是数组的指针。
返回数组指针的三种方式:类型别名,尾指针,decltype
使用类型别名:
typedef string arr[10]; arr& func();
返回尾指针类型:
auto f()->string(&)[10];
使用decltype关键字
string str[10]; decltype(str) &f();6.4 函数重载
重载函数:同一个作用域内函数名称相同,形参列表不同。
编译器会根据传递实参的类型和函数的形参类型确定执行函数。
void print(const char *p); void print(const int *beg,const int *end);
形参与const
顶层const的实参和普通的实参无法区别,比如
int f(int a); int f(const int a); int f(int *a); int f(int const* a); ~~//指针本身是一个常量,不能改变指针~~
无法进行区别,不过拥有底层const的指针和引用可以进行区分,如
int f(int& a); int f(const int& a); int f(int* a); ~~//指针本身是一个常量,不能改变指针~~ int f(const int* a); ~~//指针指向的对象是一个常量,可以改变指针~~
编译器会通过实参是否是常量来判断应该调用哪一个函数。
在重载函数中会遇到一种情况,在执行第一个函数时返回的是类型A,比如const int,在第二个函数中需要使用到类型B 比如 int型,可以使用const_cast函数做类型转换。
详解 c++ 的 const_cast 转换
在使用重载函数时也要注意其作用域。
默认实参:在函数反复多次调用中,都被赋予相同的值。
就是在定义时给某个形参赋予默认值,如果在调用函数的过程中,不初始化该形参,就会使用默认的实参。在调用过程中,编译器会按照位置解析,所以函数调用只能省略尾部的实参。
默认实参一般被声明在头文件中,不能使用局部变量修改默认实参的值。
C++ 默认实参
内联函数
内联函数用于优化规模较小,流程直接,频繁调度的函数。在函数前加上inline的关键字就可以向编译器发出请求,函数在调用点上内联的展开。
内联函数
constexper 函数
用于常量表达式的函数,函数的返回值及所有的形参类型都得是字面值类型,并且函数体中只有一条return语句。在执行任务初始化的时候,编译器把constexper函数的调用换成其结果值,为了能在编译的时候随时展开,constexper函数被隐式的指定为内联函数。
constexpr变量和constexpr函数
调试帮助
程序中包含一些用于调试的代码,在开发时使用,发布时屏蔽。
assert是一种预处理宏,如果变量为假,assert输出信息并终止程序的执行,如果为真则什么也不做。
assert(expr)
assert定义在cassert头文件中,由预处理器管理,一般用于检查不能发生的条件。
assert的行为依存于NDEBUG的预处理变量,如果NDEBUG被定义了,那么assert什么也不做,如果没有被定义,assert就会运行检查



