理由:
用数组指针+数组大小作为参数的接口很容易出错。指向数组的指针必须依靠其他途径传递其大小。
举例:
//copyfrom[p:p+n)to[q:q+n)voidcopy_n(constT*p,T*q,intn);如果q的元素数少于n会怎么样?我们会覆盖一些无关的内存。如果p的长度小于n会怎么样?我们可能复制了一些无关的内存。任何一种情况,都导致了未定义的行为,可能是很难处理的bug。
voidmy_copy_n(constchar*p,char*q,intn){for(;n0;n--){*q=*p;p++;q++;}}intmain(){charpp[]="hello";charqq[]="hel";coutqqendl;my_copy_n(pp,qq,5);coutqqendl;charpp1[]="hel";charqq1[]="hello";coutqq1endl;my_copy_n(pp1,qq1,5);coutqq1;turn0;}helhelloellohellohel替代方案:
考虑显式地用span
voidcopy(spanconstTr,spanTr2);//copyrtor2反例:voiddraw(Shape*p,intn);//poorinterface;poorcodeCirclearr[10];//...draw(arr,10);给参数n的值如果是10可能会出错:C语言里数组下标的不成文的习俗是[0:n)即包括0,不包括n。更坏的情况是,调用draw()函数在编译时没有问题,数组隐式的转换成了指针(数组衰减),另一个隐式转换:Circle转成了Shape。draw()函数无法逐个访问数组的元素,因为无从知道元素本身的大小(Shape和Circle大小不一)。
替代方案:
使用支持类,确保元素数量可知,避免危险的隐式转换。
比如:
voiddraw2(spanCircle);Circlearr[10];//...draw2(spanCircle(arr));//deducethenumberofelementsdraw2(arr);//deducetheelementtypeandarraysizevoiddraw3(spanShape);draw3(arr);//error:cannotconvertCircle[10]tospanShapedraw2()得到与draw()同样数量的信息。但是不在会隐式转换Circle类型。
例外:
使用zstring和czstring表示C风格的\0结尾的字符串。这时候,要用GSL的std::string_view或spanchar避免错误的范围。
强化:
(简单)隐式的将数组类型转换成指针类型的地方,报警。允许例外情况:zstring和czstring指针。
(简单)指针类型的数值计算,报警。允许例外情况:zstring和czstring指针。
C++核心指南是由C++创始人BjarneStroustrup和ISO/ANSIC++标准委员会秘书HerbSutter领导开发的关于如何正确高效使用C++的在线文档。就像C++语言本身一样,这些指南是许多组织中许多人多年讨论和设计的结果。kimim