函数的基本构成
- 输入
- 实参传值给形参
- 传值参数:拷贝复制,基本类型和指针。
int n = 0; i = 42;
int *p = &n, *q = &i;
*p = 42; // n的值发生改变,p的值并不会发生改变。
p = q; // p 的指向发生了改变
所以说,指针作为形参,只是存储了变量的地址。就是说调用函数的时候,实参地址传递给形参,形参拷贝实参的值,也就是地址。说明了参数调用时,发生的是值拷贝。但是通过解引用运算符(*)可以进行实参的赋值操作
void reset (int *ip){
*ip = 0; // 解引用操作,改变其所指对象的值;
ip = 0; // 只改变了ip 的局部拷贝,并不影响实参的值。
}
换句话来说,由于指针也是对象,所以当指针作为形参时,指针的值完成了从实参到形参的拷贝。形参作为被调函数的局部参数。当调用结束后,函数的形参被销毁。
经典例子
// 并不能交换实参的值
int a = 1; b= 2;
void swap(int x, int y){
int temp;
temp = x;
x = y;
y = temp;
}
理解思路:程序顺序执行的时候,其实是不断地开栈清栈的过程,作为声明的全局变量,他拥有属于他的内存。调用函数的过程是值拷贝的过程。被调函数想改变全局的变量,只有可能通过绑定地址来操作。因为本质上来说,形参与实参都会开辟内存,只不过形参的生存期仅在函数调用的时间段。当被调用结束后,形参的生存期结束。释放内存。引用和指针都是一种绑定的操作。
但是现在基本上程序中基本上不会出现这种代码,因为形参基本上都是传引用参数,这样的好处有很多,避免了拷贝会出现的大规模开内存的情况。因此,引用传递参数会天然的绑定到实参中,如果程序的本意并不是改变实参,那么常见const 形参,如果要改变实参,就可以使用引用,避免拷贝。
- 传引用参数
绑定类型的典范,建议使用引用作为形参,来避免拷贝。
当不修改,实参的值时:建议使用 const 引用传参。
修改实参时,也建议通过引用来避免拷贝运算。 - 初始化与赋值操作是两种不同的操作
- 非const 的初始化操作注意值对应。
- const 形参注意底层const 的误区。
建议常量引用的类型避免了底层const的报错;
void fcn(const int i) // fcn 能读取i ,但不能写;
void fcn(int i ) // 重复定义,因为初始化的时候会忽略掉顶层const
- 数组作为形参
数组这种类型不允许拷贝(感觉所有占大内存的数据类型都是不允许拷贝的会消耗栈的空间)。所以当其作为形参时,数组会被转化成指针。
void print(const int*);
void print(const int[]);//等价表达
void print(const int[10]);//传递的函数类型是const int *
- 由于数组有大小限制,因此要特别注意数组形参的大小。
void print(const int *beg, const int *end){
while (beg != end)
cout << *beg++ << endl;
}
void print(const int ia[], size_t size){
for (size_t i = 0; i != size; i++) // for (auto elem : ia)
cout << ia[i] << endl; // cout << elem << endl;
}
- 多维数组
多维数组的定义实际上是数组的内容是数组。因此执行拷贝操作,实际上是做的将指针指向数组。
void print (int (*matrix) [10],int rowsize)
void print (int matrix[] [10], int rowsize) // 等价操作
[] 下标操作符,& 取地址操作符,实质上都会反馈迭代器操作,也就是指针。
- main :处理命令行选项
有时候要给main 函数传递参数,根据一组选项来确定函数要执行的操作。
int main (int argc,char *argv[]); // argv大小为argc的装着C风格字符串的数组。
int main (int argc, char **argv[]) //等价写法
- 形参可变
intitializer_list <T> lst; 存储可变大小的相同类型的一种形参,支持迭代器操作。
2.返回值
- 可以饮用返回,不发生临时变量的拷贝动作,同时还可以作为左值;
deltype (左值) 返回 引用类型。引用类型是可以作为左值的,也就是说要赋值。 - auto 和 deltype 的用法
略 - 不要返回局部对象的引用或者指针
- 返回数组数组指针的写法
int arr[10];
int *p1[10]; // 十个指针的数组
int (*p) [10] = &arr; // 指向数组的指针
int (*func(int i))[10];
auto func(int i) -> int (*) [10];
- 函数指针和lambda 表达式
bool lengthCompare(const string &, const string &);
bool (*pf) (const string &,const string &);// 函数指针
pf = lengthCompare;// pf 指向lengthCompare 函数
pf = &lengthCompare //等价说法,&可选;
网友评论