1、指针形参 vs 引用形参 优缺点
当函数需要处理数组且函数体不依赖于数组的长度时,应使用指针形参;其他情况下应使用引用形参
指针形参的优点:可以明确地表示所操作的是指向数组元素的指针,而不是数组本身,而且可以使用任意长度的实参数组来调用函数;
缺点是函数体不能依赖于数组的长度,否则容易造成数组内存的越界访问,从而产生作物的结果或者导致程序崩溃。
引用形参的优点:在函数体中依赖数组的长度是安全的,其缺点是限制了可以传递的实参数组,只能使用长度匹配的实参数组来调用函数。
2、编写程序设计数组元素之和,要求编写函数三次,每次以不同的方式处理数组边界;
#include <iostream>
using namespace std;
int sum1(int* begin,int* end)//way1:传递指向数组第一个和最后一个的下一个位置的指针;
{
int sum=0;
while(begin!=end)
{
sum+=*begin++;
}
return sum;
}
int sum2(const int a[],size_t size)//way2:传递数组的大小
{
int sum=0;
for(size_t ix=0;ix!=size;ix++)
{
sum+=a[ix];
}
return sum;
}
int sum3(int* begin,size_t size) //way3:传递指向数组第一个元素的指针和数组的大小
{
int sum=0;
int *p=begin;
while(p!=begin+size)
{
sum+=*p++;
}
return sum;
}
int main()
{
int a[]={1,2,3,4};
cout<<"sum1计算结果为:"<<sum1(a,a+4)<<endl;
cout<<"sum2计算结果为:"<<sum2(a,4)<<endl;
cout<<"sum3计算结果为:"<<sum3(a,4)<<endl;
cout << "Hello world!" << endl;
return 0;
}
3、编写程序求vector<double>中所有元素之和
#include <iostream>
#include <vector>
using namespace std;
//传递元素迭代器来处理元素
double vectorSum(vector<double>::iterator begin,vector<double>::iterator end)
{
double sum=0.0;
while(begin!=end){
sum+=*begin++;
}
return sum;
}
int main()
{
vector<double> dvec;
//输入vector元素
cout<<"请输入vector中double类型的元素,以ctrl+z结束"<<endl;
double dval;
while(cin>>dval)
dvec.push_back(dval);
//求元素之和并输出结果
cout<<"vector<double>中元素的求和结果为:"<<vectorSum(dvec.begin(),dvec.end())<<endl;
return 0;
}
4、编写一个主函数main,使用两个值作为他们的实参,并输出它们的和;
#include <iostream>
#include <stdlib.h>
using namespace std;
//第一个形参argc用于传递数组中字符串的个数;第二个形参argv是一个C风格字符串数组;
int main(int argc,char **argv)
{
//检查命令行参数
if(argc!=3){
cout<<"you should use three arguments"<<endl;
return -1;
}
//使用标准库函数atof将c风格字符串转换为double型数据
cout<<"Summation of"<<argv[1]<<"and"<<argv[2]<<"is"<<(atof(argv[1])+atof(argv[2]))<<endl;
return 0;
}
5、编写程序使之可以接受本节介绍的命令行选项,并输出传递给main的实参的值;
#include <iostream>
using namespace std;
int main(int argc,char **argv)
{
cout<<"arguments passed to main():"<<endl;
for(int i=0;i!=argc;++i)
cout<<argv[i]<<endl;
return 0;
}
6、函数什么时候返回引用,什么时候返回const引用;
返回指向在函数调用之前已存在的对象的引用是正确的
放不希望返回的对象被修改时,返回const引用是正确的
7、形参,局部变量,静态局部变量的差别;并给出一个有效使用了这三种变量的程序例子
本质上:三种都属于局部作用域中的变量,其中,局部变量又可区分为普通(非静态)局部变量和静态局部变量
差别在于:
(1)形参的作用域为整个函数体,而普通(非静态)局部变量和静态局部变量的作用域为:从定义处到包含该变量定义的块的结束处;
(2)形参由调用函数时所传递的实参初始化;而普通(非静态)局部变量和静态局部变量通常用初始化式进行初始化,且均在程序执行流程第一次经过该对象的定义语句时进行初始化。静态局部变量的初始化在整个程序执行过程中只进行一次;
(3)形参和普通(非静态)局部变量均属于自动变量,在每次调用函数时创建,并在函数结束时撤销;而静态局部变量的生命期却跨越了函数的多次调用,它在创建后直到程序结束时才撤销;
例子:
#include <iostream>
using namespace std;
//用于辅助求阶乘的函数
int fac(int x) //x为形参
{
/*result为静态局部变量(确保不迟于在程序执行流程第一次经过该对象的定义语句中进行初始化,这种对象一旦被创建,在程序结束前都不会被撤销。当定义静态局部对象的函数结束时,静态局部对象不会撤销。在函数被多次调用的过程中,静态局部对象会持续存在并保持它的值 )*/
static int result=1;
result*=x;
return result;
}
int main()
{
int upLmt ; //upLmt为普通(非静态)局部变量
cout<<"Enter value of upper limit:"<<endl;
//依次输出[1.。。uplmt]只见所有整数的阶乘
cin>>upLmt;
for(int i=1;i<=upLmt;++i)
cout<<i<<"!="<<fac(i)<<endl;
return 0;
}
8、编写函数,使其第一次调用时返回0,然后再次调用时按顺序产生正整数(即返回其当前的调用次数)
#include <iostream>
using namespace std;
//用于辅助求阶乘的函数
size_t count_calls()
{
static size_t ctr=-1;//ctr的生命期将跨越函数的多次调用、
return ++ctr;
}
int main()
{
for(size_t i=0;i!=10;++i)
cout<<count_calls()<<endl;
return 0;
}
9、内联函数避免函数调用时候的开销,将函数设置为内联函数,通常就是将它在程序中每个调用点上“内联地”展开;内联函数应该在头文件中定义;