函数编程时的优良习惯

    xiaoxiao2021-03-25  42

    优良的函数编程习惯: 1.使用断言检测函数参数的合法性 2.使用const提高函数的健壮性 3.全面思考提高代码的鲁棒性 4.return的良好习惯 1.1assert的使用: assert只有在Debug版本才有效,作用是在函数的入口处检测参数的有效性; 使用assert目的是捕捉在运行时不应该出现的非法情况。 非法情况:一般是由用户输入错误导致的 错误情况:一般是程序运行过程中自然出现的,这时一定要做相关的处理, 不能使用assert; 实例: malloc 动态申请内才能失败是错误情况不能使用断言处理 //错误示例 int *pBuf=(int*)malloc(sizeof(int)*1000); assert(pBuf!=NULL); //正确示例 int *pBuf=(int*)malloc(sizeof(int)*1000); if(NULL==pBuf)//把常量放在前面,避免一不小心将等号==写成赋值= { } else {} 2.1用const修饰函数的参数 1.如果参数用于输出,不论它是什么数据类型,是采用指针传递还是引用传递, 都不能加const,否则会失去作用 2.如果输入参数采用“指针传递“,那么const修饰可以防止意外的修改该指针所 指向的内存空间,起到保护作用。如: void strcpy(char *strDest,const char *strSrc); 3.如果传入参数采用“值传递”,由于函数将自动用实参的拷贝初始化形参,因此 即便在函数内修改了该参数,改变的也只是堆栈上的拷贝而不是实参,所以一般 不使用const修饰; 4.对于ADT/UDT的输入参数,一般将值传递改为const &传递,目的是提高效率, 例:将 void Fun(A a)改为 void Fun(const A &a);对于基本类型参数一般不这 样做,因为引用的内部实现是指针,基本数据类型大小较小,也无拷贝构造所以 达不到提高效率的目的 2.2用const修饰函数的返回值 1.如果给“指针传递”的函数返回值加上const修饰符,那么函数返回值是一种契约 性常量,不能被直接修改,并且该返回值只能被赋给加const修饰的同类型指针。 例如; const char *GetString(void) 如下会出现编译错误 char *str=GetString(); 正确用法: const char *str=GetString(); 2.如果函数返回值采用“值传递”的方式,在一般情况下函数会把返回值复制到外部 的临时的储存单元中去,所以加const没有什么意义 4.1return的良好习惯 1.return不要返回栈空间的“指针”或者“引用”,因为该内存单元在函数体结束时会自 动释放,例: char *Fun(void)//如果函数不传参最好加上void,防止在c语言中出现二义性 { char *str[]="change world";//str数组在函数堆栈上,并用字符串常量初始化 //在末尾自动加'\0' cout<<sizeof(str)<<endl; //13 cout<<streln(str)<<endl; //12 return str //该语句存在隐患,str指向的内存单元将被释放 } 但是下列程序是正确的: const char *Fun(void)//如果函数不传参最好加上void,防止在c语言中出现二义性 { const char *p="change world";//字符串常量放在程序的静态数据区 //在末尾自动加'\0' cout<<sizeof(p)<<endl; //4,指针大小 cout<<streln(p)<<endl; //12 return str //返回字符串常量的地址 } 2.如果函数返回值是一个对象,要考虑return语句的效率,例如 return String(s1+s2);这是临时对象的构造语法,表示创建一个临时对象并返回它 效率明显优于 String res(s1+s2); return res; 上述代码将发成三件事情: 1.res对象被创建,同时调用相应的构造函数完成初始化 2.调用拷贝构造函数,把res复制保存到返回值的外部储存单元中; 3.res在函数结束时被销毁(调用析构函数); 而第一种返回临时变量的做法,编译器直接把临时对象创建并初始化在外部单元中, 省去了拷贝和析构的开销 类似不要把 return(x+y);写成 int temp=x+y; return temp;代码会不易读; 更详细内容见高质量c/c++编程
    转载请注明原文地址: https://ju.6miu.com/read-34589.html

    最新回复(0)