C++学习之路--程序结构(1)

一、函数相关基础

  1. 若函数名不再名称空间中定义,它就是全局的,否则要用名称空间的名称来限定它;

  2. 执行不同动作的函数通常应拥有不同的名称;

  3. 通过调用时指定的实参给函数传递信息,这些实参需与函数定义中出现的形参一致,当执行函数时,指定的实参将代替函数定义中使用的形参;
    函数形参与实参

  4. 函数的主要优点之一是根据需要可以在程序的不同位置执行任意次;

  5. 对函数而言,形参名称和函数体中定义的任何变量都是局部变量,变量产生于定义它的位置,在包含它的代码块结束时不复存在(注意:声明为static的变量除外);

  6. 若当函数停止执行时,变量result不复存在,如何返回计算结果?
    答案:系统将自动生成返回值的副本,该副本可以在程序中的返回点获得;

  7. return语句将result的值返回到调用函数的位置;

  8. 替代函数语法:
    auto power(double x, int n)->double
    {

    }
    函数的返回类型放在函数头中->后,称为拖尾返回类型
    auto关键字告诉编译器,返回类型在以后确定;

  9. 引入替代语法的意义:当函数的返回类型需要虽函数体的执行结果而变化时,就需要使用函数模板,者不能使用旧语法来定义,而替代语法允许这么做;

  10. 函数原型给编译器提供了为检查我们是否在正确 使用函数而需要的基本信息。函数原型指定了要传递给函数的形参、函数名和参数的返回值类型,基本上包含出现在函数头中的相同信息,只是增加了一个分号;

  11. 从其他函数内调用一个函数时,该函数的原型或定义必须在调用语句之前,通常放在程序源文件的开头部分,注意:函数原型后面要加分号;

  12. 函数原型中指定的形参名称与定义函数时函数头中使用的名称不同,大多数情况下,函数原型和函数定义中的函数头使用相同的名称;
    13. 各种传递机制:
    (1)[ 按值传递]
    function为
    int incr10(int num)
    {

    }
    声明:
    int incr10(int* num);
    main()函数中的调用:

(2)[给函数传递指针实参 ]
以指针作为形参可以使函数处理调用者实参,原因:
指针是一个变量的地址,若创建该地址的副本,则副本仍然指向相同的变量;
function为
int incr10(int* num)
{

}

声明:
int incr10(int* num);
main()函数中的调用:
cout<<endl<<“incr10(pnum)=”<<result;

main()函数和incr10() 函数分别输出发送和接收的地址,以确认两个位置使用的实际上是相同的地址。

(3)[给函数传递数组 ]
仍然应用按值传递的方法传递实参,也不会复制被传递的数组。
编译器将数组名转换为指针,指向数组头部的指针副本通过按值传递机制被传递给函数。数组是唯一不能按值传递的类型;
function为
double average(double array[], int count)
{

}

main()函数中的调用:
cout<<endl<<"Average = " <<average(values, _countof(values))<<endl;

average()函数可以处理任意长度的数组,
(4)[给函数传递引用实参 ]
将函数的某个形参指定为引用,将改变给该形参传递数据的方法。使用的不是按值传递–其中在传递给函数之前复制实参,而是按引用传递,即形参其实是被传递实参的别名。该机制不再复制所提供的实参,允许所提供的实参,允许函数直接访问调用函数中的实参。同时意味着,传递和使用指向值的指针所所需的取消引用操作也是多余的。
function为
int incr(int& num) //num为引用,所以输出的是数据之而非地址值
{

}
main()函数中的调用:
result=incr10(value);
实参的值并未传递给函数。函数的形参初始化为实参的地址,因此函数中只要使用形参num,就直接访问调用函数中的实参。
每当调用该函数时,都将创建和初始化函数形参的引用,而当函数结束时将它销毁。因此每次使用函数时,得到的都是全新的引用。
引用是另一个变量的别名,因此可以用作引用该变量的替代方法。使用引用与使用原来的变量名是等价的。
lvalue引用形参对应的实参必然会导致某些数据永久地存储在内存中。

(4)[使用const修饰符 ]
可以给函数的形参使用const修饰符,以告诉编译器我们不想以任何方式修改这个形参。这样编译器将检查代码是否确实没有修改实参,而且当使用常量实参时不会产生错误消息;
用lvalue 引用形参,得到了两方面的好处:
A.可以编写直接访问调用者实参的函数,而且避免了按值传递机制中隐式的复制;
B.若不打算修改某个实参,则只需要给lvalue 引用类型使用const修饰符,就能避免意外修改该参数。

(5)[rvalue 引用形参 ]
虽然rvalue引用形参可以引用一个rvalue—即表达式的临时结果,但rvalue 引用形参本身并不是一个rvalue,而是一个lvalue。有时我们希望将rvalue引用形参从lvalue转换成rvalue。

(6)[main()函数的实参]
可以将main()函数定义为不带任何形参,也可以制定一个参数列表,以允许main()函数从命令行上获得值。从命令行上作为实参传递给main()的值总是解释为字符串。若希望main()函数从命令行上获得数据,则必须像如下定义main()
int main(int argc, char* argv[])
{

}
第一个形参 argc:命令行上出现的、包含函数名在内的字符串的数量,始终至少为1,因为至少要输入程序名,接收的实参数量取决于为了执行程序而在命令行上输入的内容;
第二个形参 argc[] :是一个数组,它包含指向这些字符串的指针,还有一个为空值的附加元素

举例:
举例
由上可知:若希望包括空格的字符串作为单个字符串被接受,则必须将其包围在双引号内。

(7)[接受数量不定的函数实参]
可以将函数定义成能够接收任意数量的实参。将省略号(三个句点…)写在函数定义中的形参列表的最后,即可表示调用该函数时可以提供数量的可变实参。
int sumValues(int first, …)
{

}
函数定义中至少要有一个普通形参,但也可以有多个。省略号必须总是放在形参列表的最后。
C++库在cstdarg头文件中定义了va_start、va_arg和va_end宏,用于函数代码弄清自己被调用时接收的是什么。

14. 从函数返回值
[1]返回指针
double* treble(double data )
{
double result {};
result=3.0*data;
return &result;
}
返回地址的规则:永远不要从函数中返回局部自动变量的地址。

返回指向某些有用数据的指针,以便最终能够返回多项数据,一种方法:
A. 动态内存分配,使用new操作符,可在空闲存储器中创建一个新变量,该变量一直存在,直至最终被delete销毁,或直到程序结束。
例如:
double* treble(double data)
{
double* result{new double{}};
result =3.0data;
return result;
}
注意:使用动态内存分配时,每次调用该函数时都要多分配一些内存。当不再需要内存时,主调程序需将其删除,否则将导致空闲存储器的内存被逐渐消耗,直到某个时刻内存用尽且程序失败。
此类问题即为:内存泄漏
B.使用智能指针,就不需要使用delete释放用new分配的内存了,使用智能指针也可避免内存泄漏的危险。

[2]返回引用
例如:
double& lowest(double a[], int len)
{
int j{};
for(int i{1};i<len;i++)
if(a[j]>a[i])
j=i;
return a[j]; //因为返回类型声明为引用,所以实际返回的是数组元素a[j]的引用,而非该元素包 含的值
}
函数lowest() 的原型使用double&作为返回类型的说明,故属于“double的引用类型”
return a[j]; //因为返回类型声明为引用,所以实际返回的是数组元素a[j]的引用,而非该元素包 含的值。
返回引用的规则:永远不要从函数中返回局部变量的引用。
NOTE
注意管理从不同的线程中访问全局变量的方式:
当多个线程都可以访问某个全局变量时,必须处理好的基本问题是:一个线程使用全局变量时,另一个线程可以修改该变量的值,在这样的情况下,最好的解决方案是完全避免使用全局变量。

[3]函数中的静态变量
为了创建在这次与下次函数调用之间其值继续存在的变量,可以在函数内将某个变量声明为static。
例如:static int count {};
函数内静态变量的初始化仅仅发生在第一次调用该函数的时候。事实上,初次调用函数时将创建并初始化静态变量。之后,该变量在程序执行期间将继续存在,退出函数时该变量包含的任何值都可以在下次调用函数时使用。

15.递归函数的调用
除非遇到的问题特别适于使用递归函数,或没有明显的替代方法,否则使用其他方法一般(如循环)会更好。效率更高, 系统开销更小。
具体说举例说明:
迭代的劣势

猜你喜欢

转载自blog.csdn.net/weixin_41646537/article/details/86556211