编译器能以任意顺序对形参进行求值
函数的返回类型不能是数组类型和函数类型。
函数开始时为形参分配内存,一旦函数结束,形参也就被销毁了。

如果弄成静态局部变量,那么回到程序终止结束时才被销毁。

void fo()
{static int a ;   //只在第一次初始化a++;             //保存了前次被调用后留下的值return ;
}
//所有的全局变量都是静态变量,而局部变量只有定义时加上类型修饰符static,才为局部静态变量

形参类型决定了形参与实参的交互方式

f(int a,int b) 被调用时可以看成  f(int a = x,int b = y);
f(int &a,int &b) 被调用时可以看成  f(int &a = x,int &b = y);

使用引用避免拷贝:
拷贝大的类类型或者容器的对象比较低效,甚至有的类类型不支持拷贝操作

参数的const:
顶层const会被忽略,所以两个fcn的参数是一样的(顶层const没法区分参数)

void fcn(const int a){}
void fcn(int a){}

尽可能使用常量引用:

void find(string &s){
}
void find_char(const string &s){
}
find("hhh");                  //error 普通引用不能引用字面值
find_char("hhh");             //ok

但底层const看成不同的参数(作用于不同的对象 常量or非常量)
编译器可以通过实参是否是常量来判断调用哪一个(而且非常量优先选择非常量版本)

Record look(Account *)
Record look(const Account *)
Record look(Account &)
Record look(const Account &)

含可变参数:

Initializer_list:
initializer_list是C++标准程序库中的一个头文件,定义了C++标准中一个非常轻量级的表示初始化器列表的类模板initializer_list及有关函数。
与vector不同的是,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。
initializer_list lis(ls);
initializer_list lis = ls;   //原始列表和副本共享元素

C++11允许构造函数和其他函数把初始化列表当做参数

void fcn(initializer_list<int> ls)
{for(auto i : ls){cout << i <<" ";}cout << endl;
}
int main()
{fcn({1,2,3});return 0;
}
class node
{public:node(int a,int b){}node(initializer_list<int>) {}node(){};
};
int main()
{node a;node b(1,2);node c{2,3,4,5,6};node d = {1,3,4,5,6};return 0;
}

省略符类型:

只是用与C/C++通用类型,大多数类类型在传递省略符形参时都无法正确拷贝

void foo(int a,...)
void foo(...)

返回值:

返回值的方式和初始化类似,返回值会被拷贝到函数的调用点用于初始化,如果返回引用又是另一回事。
而且别返回局部变量指针或者引用,因为函数结束一会后其所占空间会被释放掉

int& fo(int a)
{int b = a;cout << &b <<endl;return b;
}
int main()
{int &a = fo(100);         //a,b地址相同,说明并没有经过拷贝cout << &a <<endl;cout << a <<endl;
}

函数的返回类型决定返回是否为左值:

当函数返回引用的时候所得到的是左值,其它所得到的都是右值。

char &to_Get(string& a,int index)
{return a[index];
}
int main()
{string ta("abcd");cout << ta <<endl;to_Get(ta,1) = 'B';cout << ta << endl;/*abcdaBcd*/
}

返回数组指针:

数组因为不能被拷贝,所以函数不能返回数组。可以返回数组的引用和指针,只是比较麻烦.
①.利用别名简化。

typedef int arr[10];
using arr = int[10];
arr* func(int i);

②.声明一个返回指针的函数(从内往外读)

int (*a)[10];
int (*func(int a,))[10];                 //格式相似

③.尾置返回类型
在->符号后面指明函数的真正返回类型

auto func(int a) -> int(*)[10]
{
}

④.使用decltype(但是会返回数组类型,而数组又无法赋值,所以搞成指针)

int odd[] = {1,3,5,7};
decltype(odd)* func()
{return &odd;          //返回数组类型的指
}
int main()
{auto p = func();cout << p << " " <<odd <<endl;
}

重载:

函数重载:应该在函数参数个数或者形参类型上面有所不同.
如果在当前作用域中找到了所需的函数名,那么编译器会自动忽略外层作用域的同名实体。(不同作用域不能重载函数名)

void Print(string a);
void Print(double a);
void f(int a)
{void Print(int);print("abc");     //error:与int不符Print(2.5);       //输出了int
}
void Print(double a){ cout << "double " << endl;}
void Print(int a){cout << "int" << endl;}
void Print(string a){cout << "string" << endl;}

默认实参:

一旦某个形参被赋予了默认实参,那后面全部都要有默认值。 而且函数调用时,只能省略尾部实参

windows = screen(,,'s');      //error
windows = screen('s');

函数可以被声明多次,但是一个形参只能被赋予一个默认值。

string screen(sz,sz,char = ' ');
string screen(sz,sz,char = '?');             //error,重复声明
string screen(sz=24,sz=80,char);             //correct,添加默认实参

(局部变量不能作为默认实参)

int pa = 100;
void fo(int a = pa);              //默然实参为pa
void f()
{int pa = 80;                  //隐藏了外部的pafo();                         //没改变默认值
}
int main()
{f();
}
void fo(int a)
{cout << a <<endl;
}

内联函数:

调用函数比一般的求表达式的值要慢一点,大多数机器上,一次函数调用包含着很多工作:调用前先保存寄存器,并在返回时恢复;
可能需要拷贝实参;程序转下一个新的位置继续执行。
内联函数(优化规模小,流程直接,调用频繁的函数; 有的编译器不支持):

cout<<shorterString(s1,s2)<<endl;
//在编译器看来会转换成
cout << (s1.size() <= s2.size() ? s1:s2) <<endl;

constexpr函数:

编译器把对constexpr函数的调用替换成它的结果了,被隐式地指定为内联函数。
允许返回值并非一个常量?
A (non-template) constexpr function must have at least one execution path that returns a constant expression
//必需要能返回至少一个常量表达式

constexpr int f(bool b) { return b ? throw 0 : 0; }     // OK
constexpr int f() { return f(true); }     // ill-formed, no diagnostic required
template<bool B> constexpr int g() { return f(B); }    // OK
constexpr int h() { return g<true>(); }    // ill-formed, no diagnostic required
http://stackoverflow.com/questions/31206937/a-constexpr-function-is-not-required-to-return-a-constant-expression\

但如果把函数用在需要常量表达式的上下问时,则编译器会检测函数结果是否符合要求
内联函数和constexpr函数可以在程序中被定义多少,通常被定义在头文件

assert:
一种预处理宏,行为类似内联函数。 assert(expr)//cassert头文件,由预处理器管理,不需要命名空间
assert(word.size() > threshold);
如果定了NDEBUG预处理变量,那么assert什么也不做

参数匹配:

1.与被调用函数同名 2.其声明在调用点可见
3.形参数量相同 4.实参和形参的类型相同,或者能够转换
然后从可行的当中找出最佳匹配
匹配成功:①每个实参的匹配都不劣于其它可行函数的匹配
②至少有一个实参匹配优于其它
否则会产生二义性

void f(int a,int b)
void f(double a,double b)
int main()
{f(3,2.15);
}

上面这个例子,两个函数中找不到一个脱颖而出的。 所以会产生二义性。
//要避免强制类型转化,出现只能说明我们的形参集合设置的不合理

匹配等级:
①精确匹配:
1.实参和形参的类型相同
2.从数组类型或者函数类型转换它们的对应的指针类型
3.想实参中添加顶层const或者删除顶层const
//2016年11月20日 22:00:24
②通过const转换 (添加底层const:const&什么的)
③通过类型提升 (小类型提升为大类型)
④通过算术类型转换或者指针转换 (运算符的运算对象转换成最宽;0或NULL转换成任意指针,任意非常量对象指针->void,任意对象->const void
⑤类类型转换

void f(float x);
void f(int x);
f(3.45);   //double型,而所有算术转换等级相同,产生二义性
void f(int a);
void f(short b);
f('a');          //类型提升,但是会提升为较大范围的int。只有类型是short时才会调用short版本

函数指针:

函数的类型是由它的返回类型和行参类型决定的。 函数可以自动地转换成指针,指针可以调用该函数

bool lengthCompare(const string&,const string &);
bool (*p)(const string&,const string&);
p = lengthCompare;
p = &lengthCompare;    //等效,函数名会转换成指针
bool t = p("hello","bye");
bool t = (*p)("hello","bye");      //等效

对于重载函数,编译器会通过指针类型选哪个函数,指针类型必需与重载函数的某一个精确匹配.
函数指针可以作为一个函数的形参。
简化函数指针代码 decltype and typedef:

typedef bool func(const string&,const string&);         //函数
typedef bool (*func)(const string&,const string&);      //函数指针
typedef decltype(lengthCompare) func2;
typedef decltype(lengthCompare) *func2;
decltype()会返回一个函数类型而且不会自动转换成指针

返回函数的指针:

using p = int(int*,int );
using tp = int(*)(int*,int );tp f1(int);              //correct   tp是指向函数的指针
p f1(int);               //error  p是函数类型,不能返回一个函数
p* f1(int);              //correct
int (*f1(int*,int))(int*,int );     //直接声明一个返回函数指针的函数

首先f1前面*,所以f1返回一个指针;指针类型包含形参列表,所以指针指向一个函数

尾置型:

auto f1(int) -> int (*)(int*,int);

转载于:https://www.cnblogs.com/Przz/p/6414337.html

C++Primer学习——函数相关推荐

  1. C++ Primer 学习笔记(第四章:表达式)

    2019独角兽企业重金招聘Python工程师标准>>> ##C++ Primer 学习笔记(第四章:表达式) [TOC] ###4.1 基础 左值和右值: 当一个对象被用作右值的时候 ...

  2. 如何正确的通过 C++ Primer 学习 C++?(转自知乎)

    作者:dawnmist 链接:https://www.zhihu.com/question/32087709/answer/54936403 来源:知乎 著作权归作者所有,转载请联系作者获得授权. 个 ...

  3. 【C++ Primer 学习笔记】: 容器和算法之【泛型算法】

    本系列博客主要是在学习 C++ Primer 时的一些总结和笔记. [C++ Primer 学习笔记]: 容器和算法之[泛型算法] 本文地址:http://blog.csdn.net/shanglia ...

  4. 如何正确通过 C++ Primer 学习 C++?

    链接:https://www.zhihu.com/question/32087709 编辑:深度学习与计算机视觉 声明:仅做学术分享,侵删 即将读研,虽然考的是本专业(GIS),但是研究生读的专业在计 ...

  5. C++ Primer 学习笔记 第十章 泛型算法

    C++ Primer 学习笔记 第十章 泛型算法 336 find函数 #include <iostream> #include <vector> #include <s ...

  6. C语言入门学习——函数的使用

    函数的概述 C 程序是由函数组成的,我们写的代码都是由主函数 main()开始执行的.函数是 C 程序的基本模块,是用于完成特定任务的程序代码单元. 从函数定义的角度看,函数可分为系统函数和用户定义函 ...

  7. 怎么用计算机函数图像处理,应用图形计算器学习函数注意“想、作、思”结合...

    提要 引入图形计算器在一定程度上激发了学生学习数学的热情,但仅仅去追求一些新奇的.表面的东西就偏离了数学的本质:还应当将这一功能与纸笔运算.逻辑推理.列表作图之间达成一种平衡,更要发挥信息技术的优势, ...

  8. bp学习函数matlab代码,小范学数量经济学之四:BP神经网络预测的MATLAB模拟代码

    股票价格预测神器:BP神经网络预测的matlab模拟代码: 自动优选神经元个数: 自动迭代15000次,精度0.001: 代码运行效果图: 原始代码自此处开始: % 本代码由重庆科技学院范巧副教授于2 ...

  9. C++Primer学习笔记:第6章 函数

    通过调用运算符()调用函数 函数的调用完成两项工作: 用实参初始化函数对应的形参 将控制权转移给被调用函数:主调函数的执行被暂时中断,被调函数开始执行 尽管实参与形参存在对应关系,但是并没有规定实参的 ...

最新文章

  1. 【原创】CSSOO的思想及CSS框架的应用(未整理完)
  2. button 元素的css3旋转动画
  3. colab出现input output error问题
  4. 重启计算机后桌面顺序是反的,Win10系统为什么重启电脑之后桌面上的图标排列顺序被打乱该如何处理...
  5. js 字符串插入_前端利器React,为什么推荐JSX来替换JS
  6. app 怎么通过jmeter 进行性能测试
  7. Black Hat USA 2021主议题介绍
  8. EA 反向工程 导入oracle中表结构
  9. idea运行项目提示找不到或无法加载主类
  10. 修复win7便签功能
  11. pcsx2运行ps1_PS2模拟器PSX2设置及使用教程.doc
  12. c语言程序求200以内的全部素数,求100~200之间的全部素数
  13. 增强型MOSFET导通条件
  14. 前端工程师之华为手机如何打开开发者模式并进行手机调试查看原生APP效果。
  15. 《漫步华尔街》 读书笔记 part1 历史
  16. 安装Mathtype后无法使用——已解决
  17. 后端常用数据库的使用MongoDB, Redis, Mysql
  18. 集合_java集合框架
  19. 如果用户计算机已接入,计算机应用基础第七章复习题.doc
  20. darknet详解(yolo图像检测)

热门文章

  1. 手写简单的双向数据绑定
  2. 为私有Kubernetes集群创建LoadBalancer服务
  3. 2016年IoT和新的逃逸技术将会引领威胁态势
  4. 正则表达式获取TABLE里的内容
  5. python 其他函数调用 __init__ 初始化的值
  6. jQuery的.bind()、.live()和.delegate()之间区别
  7. 批量 kill mysql 中运行时间长的sql
  8. ASP.NET Web API WebHost宿主环境中管道、路由
  9. wmic 命令的一个汇总,功能很强大
  10. 利用ES6进行Promise封装总结