文章来源http://xuexi88.blogspot.com/
C++ Primer读书笔记 7章
第七章
1.形参:在形参表中定义的。并由调用函数时传递给函数的参数初始话。
实参:表达式,要求类型与形参匹配或可自动转换。
2.函数返回类型可以是内置、类类型、复合类型、void;不能返回函数或数组。
3.c++的函数必须指定返回类型,尽管是void.
4.参数列表中,如果两个参数具有相同的参数类型,不能合并声明。
5,函数声明时,参数名可省略,但定义时通常要命名,命名后才能使用。
6.编译器在编译时会检查实参形参的类型对应。
7.函数每次调用都会创建、初始化形参。
8.如果形参是非引用类型,初始化时赋值实参的值,如果是引用类型,形参是实参的别名。
9.非引用类型在初始化形参时,创造了实参的副本,这些副本在函数调用结束后消失。
10.形参如果是指针,为了保护指针所指向的对象,需要将指针定义为const *。即进制使用该指针修改对象。但是指针本身可被赋值。
11.形参如果是const非引用类型,不能修改实参的副本。
12.以下情况不适合复制实参
当需要修改实参值时,
当实参对象过大时
当无法实现复制实参值时。
13.c中经常使用指针访问修改实参,c++引用更 安全 自然。
14.如果使用引用形参的目的是仅仅是不复制对象的话,应将参数定义为const引用。
15.对于一个非const的形参,特殊的一点:不能用右值或可以转换过去的类型去初始化它。要求必须是类型完全相同的非const变量。
16.const引用可以用右值初始化的。 const int &i=9; -》 int temp=9; const int &i=temp;
17.总结:const引用可以有各种变量或右值初始化。非const引用只能用同类型的变量初始化。
指向指针的引用。
1.int *&vi; 从右向左,v1是一个引用,与指向int类型的指针相关联。
vector及其他容器类型的形参:
1.避免复制容器类型,可将其声明为引用类型。更好的做法是传递迭代器。
数组形参:
1.数组不能被自动复制。
2.可用下面三种方式指定数组形参:
void function(int*)
void function(int[])
void function(int[10])
意义相同 数组的长度是假的,编译器会将他忽略。
3.注意:如果一个单值的指针可以当作数组对待,返回的是数组的首值。
4.不需要修改数组的元素时,应将函数形参声明为const 指针。
通过引用传递数组:
1.如果函数参数是数组的引用,编译器不会将实参转换为指针而是传递数组的引用。这时数组的大小成为形参实参匹配的一个检查项。
int (&array)[10] array 是指向 int *[10] 的一个数组。
2.NULL
3. int (*i)[10];这是一个指针,指向的是一个元素为含有10个int的数组。
int *i[10];这是一个数组。
i 最先结合的操作符决定了他的类型。
main的参数:
1.char **p; 意思是p是指向char*的指针。
2.main函数可以接受两个参数,第一个是参数的个数,第二个是参数的数组。
含有省略符参数的函数:
int foo(...)
return语句
1.如果函数是void,函数体中的return可以省略。
2.return:强制结束函数。
3.循环中有return,循环外没有return不会编译报错,但是会出现未知情况。
4.非void的main,也可以没有返回值,会隐式插入一个 return 0;返回0表示成功。
5.返回引用:注意:千万不要返回局部变量的引用,函数完成后局部变量内存释放导致引用指向不确定的空间。
6.如果返回一个引用返回的是一个左值。此时函数的类型不能是const否则不能赋值了。
7.同5,也不要返回一个指向指向局部变量的指针。同样是因为局部变量被销毁。
递归
1.递归必须有个终止条件,否则会永远递归。
函数定义:
1.函数也是可以定义一次,声明多次。
2.函数原型: 函数返回类型 函数名 形参列表
3.默认实参,如果一个形参有默认值,那他后便的所有形参都要有默认值。
4.如果参数列表中有多个形参,要给后边的形参提供实参,那它前边的形参都有实参。
5.在一个文件中只能为一个形参指定默认实参一次。
6.关于函数默认实参:如果函数声明中有实参,这个实参只对包含了这个声明的文件有效,如果一个函数没有包含这个声明,而是自己使用extern来声明,可以在extern声明中指定另外的实参。
7.一个文件中一个函数可以声明多次。但是多次声明对同一个形参不能指定不同的默认值,否则是重定义。
局部对象
1.自动对象:函数调用时创建撤销。
2.静态局部对象,函数内的。这种对象一经创建,到函数结束之前不会撤销。
静态变量只初始化一次。第一次调用初始化,之后的调用不再有效。
内联函数
1.调用函数比求解表达式要慢得多。调用函数要保存寄存器,并在返回时恢复,复制实参,程序必须转向一个新位置执行。
2.inline const关键字,先后无所谓
3.内联函数:短小,并且不能是递归。
4.重要。内联函数的定义应该放在头文件中。
5.内联函数可以在程序中多次定义,但是一个文件中只能定义一次。并且所有定义必须相同。
类的成员函数
1.函数原型必须在类内定义。函数体可以在类外定义。
2.编译器,隐式,将类内部定义的函数当作内联函数。
3.成员函数有额外的、隐含的形参。当用过对象调用它的函数时,这个对象也是这个函数的参数。
4.this指针,每个成员函数(static的除外)都有一个隐含形参。 &A 一个指向本对象的指针。
5.成员函数在()后加上const,表示隐含指针为const int *this..
this 指向的是const对象,不能修改对象,这叫:常量成员函数
6.一个成员函数,不使用前缀去调用对象的任何成员,被假定为使用this实现调用。
7.在函数的形参中不能显式使用this指针
构造函数
1.构造函数无返回类型。
2.默认构造函数:将对象初始化为合理的默认状态。无形参,如果不显示定义,则:合成的默认构造函数。
3.新玩意:默认构造函数的初始化列表。p226
4.合成默认构造函数:(不是默认构造函数啊),按照变量初始化原则初始化。注意:函数中的变量不初始化。
函数重装 overload
1.形参一定要不同。
2.main函数不能重载。
3.typedef定义的类型,和源类型在形参类型中无异。
4.声明为const也不能视为不同类型,但两种情况除外。引用和指针。
函数隐藏
1.和变量名一样。内层定义的名字可以隐藏外层定义的名字。函数和变量也可相互隐藏。
重载时,函数匹配二义性
1.如果匹配的结果是多个,则是错误的。比如一个函数有默认值形参。可以编译通过,但调用会提示调用不明确。
2.经典的例子我曾经误解
#include <iostream>
#include <vector>
using namespace std;
int test(const int &a)
{
return 2;
}
int test(int &a)
{
return 1;
}
int main()
{
const int i=0;
cout<<test(i);
return 0;
}
如果i是个非const变量,则 int &a是最精确的匹配
原话:将const引用初始化为非const对象需要类型转换,而非const形参是最佳匹配。
3.用实参初始化形参时,需要使用强制类型转换,说明函数形参设计不合理。
实参类型转换
1.转换时的等级:降序排列
1> 精确匹配
2> 类型提升
3> 标准类型转换
4> 类类型转换 ??
2.枚举也是一种类型,在重载匹配时也要考虑。 p235.
指向函数的指针
1. int (*pf) (int var) pf是指某种类型指针的一个实例。
2. typedef int (*PF) (int var); 这里PF是一种类型。 PF p1=0;
3. 函数指针只能用同类型的函数、函数指针、0来初始化。
初始化时 PF p1=f_name; 和 PF p2=&f_name;等效。
4.通过指针调用函数:
PF pf1=f_name;
pf1(var); (*pf1)(var); f_name(var);
5.函数指针做形参:
形参也有两种形式:
void Fuc( bool(int var));//书上说行,实际测试不通过
void Fuc( bool (*) (int var))
void Fuc(PF pf);
即可以直接使用函数类型做形参。
6.返回值是个函数指针:比较晦涩
int (*ff(int var)) (int var1, int var2)
理解方式:ff是个函数,返回一个 int (*) (int var1,int var2)类型的指针。
同解:
typedef int (*PF) (int var1,int var2);
PF ff(int var);
7.允许将形参定义为函数类型,但是返回类型不能,必须是函数指针。
文章来源http://xuexi88.blogspot.com/
0 评论:
发表评论