//6.1函数基础
//一个典型的函数定义包括一下几个部分:返回类型、函数名字、形参列表、函数体
//6.1.1局部对象
//在C++语言中,名字有作用域,对象有生命周期
//1.名字的作用域是程序文本的一部分,名字在其中可见。
//2.对象的生命周期是程序执行过程中该对象存在的一段时间。
//自动对象
//当函数的控制路径经过变量定义语句时创建该对象,当到达定义所在的块末尾时销毁它。我们把只存在于
//块执行期间的对象称为自动对象。当块的执行结束后,块中创建的自动对象的值就变成未定义的了。
//形参是一种自动对象
//局部静态对象
//某些时候,有必要令局部变量的生命周期贯穿函数调用及之后的时间。可以将局部变量定义成static类型从而获得这样的对象。
//局部静态对象,在程序执行路径第一次经过对象定义语句时初始化,并直到程序终止时才被销毁,在此期间即使对象所在的函数结束执行也不会对它有影响
//6.1.2函数声明
//6.1.3分离式编译
//6.2参数传递
//每次调用函数时都会重新创建它的形参,并用传入的实参进行初始化。
//6.2.1传值参数
//指针形参
//6.2.2传引用参数
//6.2.3const形参和实参
//6.2.4数组形参
//实际上传入的时数组的首地址
//6.2.5main: 处理命令行选项
#include<iostream>
using namespace std;
int main61(int argc, char *argv[])
{
cout << "argc= " << argc << endl;
for (int i = 0; i < argc; i++)
{
cout << "argv[" << i << "]=" << argv[i] << endl;
}
getchar();
system("pause");
return 0;
}
//6.2.6含有可变形参的函数
//initializer_list形参
//如果函数的实参类型未知,但是全部实参的类型都相同,我们可以使用initializer_list类型的形参。
//省略符号形参
//省略符形参是为了便于C++程序访问某些特殊的C代码而设置的,这些代码使用了名为varags的C标准库功能。
//6.3返回类型和return语句
//6.3.1无返回值的函数
void swap(int &v1, int &v2) {
if (v1==v2)
{
return;
}
int tmp = v2;
v2 = v1;
v1 = tmp;
//此处无须显式的return语句
}
//6.3.2有返回值的函数
//因为含有不正确的返回值,所以这段代码无法通过编译
//bool str_subrange(const string &str1, const string &str2) {
// //大小相同:此时用普通的等号性判断结果作为返回值
// if (str1.size()==str2.size())
// {
// return str1 == str2;//正确,返回值为bool类型
// auto size = (str1.size() < str2.size()) ? str1.size() : str2.size();
// //检查两个string对象的对应字符是否相等,以较短的字符串长度为限
// for (decltype(size) i=0;i!=size;++i)
// {
// if (str1[i]!=str2[i])
// {
// return;//错误,没有返回值,编译器将报告这一错误
// }
// }
// }
//错误,控制流可能尚未返回任何值就结束了函数的执行
//编译器可能查不出这一错误。
//}
//值是如何被返回的。
//返回一个值的方式和初始化一个变量或形参的方式完全一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。
//不要返回局部对象的引用或指针。
//严重错误:
//const string &manip() {
// string ret;
// if (!ret.empty())
// {
// return ret;//错误,返回局部对象的引用
// }
// else
// {
// return "empty";//错误,是一个局部临时变量。
// }
//}
//返回类 类型的函数和调用运算符
//引用返回左值
//列表初始化返回值
#include "vector"
vector<string> process() {
return{ "functionX","a" };
}
//主函数main的返回值
//0成功,其他失败
//递归,一个函数返回了它本身即称之为递归
int factotial(int val) {
if (val>1)
{
return factotial(val - 1)*val;
}
return 1;
}
//6.3.3返回数组指针
//6.4函数重载
//如果同一作用域内的几个函数名字相同但形参列表不同我们称之为重载函数。
//例如
void print(const char*p) {};
void print(const int *p,const int *g) {};
void print(const int p[], double g[]) {};
//6.5特殊用途语言特性
//6.5.1默认实参
//6.5.2内联函数和constexptr函数
//内联函数可以避免函数调用的开销
//constexptr函数是指能用于常量表达式的函数。定义constexptr函数的方法域其他函数类似,不过要有几点约定
//函数的返回类型及所有形参的类型都是字面值类型,而且函数体中必须有一条return语句。
//6.5.3调试帮助
//assert预处理宏
//是一个预处理变量,assert(条件),如果条件为真,则什么都不做,如果为假,则输出信息并终止程序。
//NDEBUG预处理变量
int main61() {
#ifndef NDEBUG //release状态下使用
for (int i=10;i>0;i--)
{
cout << i<<ends;
}
cerr << "x ";
#endif
cout << "end\n";
system("pause");
return 0;
}
//6.6函数匹配
//确定候选函数和可行函数
//寻找最佳匹配
//含有多个形参的函数匹配
//6.6.1实参类型转换
//6.7函数指针
//函数指针指向的是函数而非对象。和其他指针一样,函数指针指向某种特定类型。
//函数的类型由它的返回类型和形参类型共同决定,与函数名无关。
bool lengthComepare(const string &, const string &);
bool (*pf) (const string &, const string &);
//使用函数指针
//pf = lengthComepare;
//pf = &lengthComepare;
//重载函数的指针
//函数指针形参
//返回指向函数的指针