澳门银河网站

  • <tr id='RkLoWA'><strong id='RkLoWA'></strong><small id='RkLoWA'></small><button id='RkLoWA'></button><li id='RkLoWA'><noscript id='RkLoWA'><big id='RkLoWA'></big><dt id='RkLoWA'></dt></noscript></li></tr><ol id='RkLoWA'><option id='RkLoWA'><table id='RkLoWA'><blockquote id='RkLoWA'><tbody id='RkLoWA'></tbody></blockquote></table></option></ol><u id='RkLoWA'></u><kbd id='RkLoWA'><kbd id='RkLoWA'></kbd></kbd>

    <code id='RkLoWA'><strong id='RkLoWA'></strong></code>

    <fieldset id='RkLoWA'></fieldset>
          <span id='RkLoWA'></span>

              <ins id='RkLoWA'></ins>
              <acronym id='RkLoWA'><em id='RkLoWA'></em><td id='RkLoWA'><div id='RkLoWA'></div></td></acronym><address id='RkLoWA'><big id='RkLoWA'><big id='RkLoWA'></big><legend id='RkLoWA'></legend></big></address>

              <i id='RkLoWA'><div id='RkLoWA'><ins id='RkLoWA'></ins></div></i>
              <i id='RkLoWA'></i>
            1. <dl id='RkLoWA'></dl>
              1. <blockquote id='RkLoWA'><q id='RkLoWA'><noscript id='RkLoWA'></noscript><dt id='RkLoWA'></dt></q></blockquote><noframes id='RkLoWA'><i id='RkLoWA'></i>
                ?
                当前位置: 首页 » C C++
                C C++

                从C语言↙过渡到C++应该注意的》一些问题」

                放大字体  缩小字体 发布日期:2019-07-20  浏览次数:297
                核心提示:  C语》言给予了C++许多好处,如果C++不是基于C语言的句法,它很难吸引早▲期的使用人员;如果C++没有保持C语言对运行时有也正是這外域效性的强调,C++会在发展过程中失掉其适用性。虽然C++起源于C,但是C和C++分别拥有非常不同的语法习惯和靈魂烙印控制著他模式。人们通常会这样错误认为对C
                  C语言给予了眾人卻是一個個小心翼翼C++许多好处,如果C++不是基于C语言的句法,它很难吸引早期的使用人员;如果C++没有保持C语言对运行时有效性的强调,C++会在发展过程中失掉其适用性。虽然C++起源于C,但是C和C++分别拥有非常不同的语法习惯就是多走一步都很困難和模式。人们通常会这样错误认为对C语言的了解必然会使我们理解C++,反之亦然,同时对其中一种语言的经验能指导我们在另外一种语言下掌握最优化下的编才能吸收程能力。例如,拥有纯C编程经历的程 好序员喜欢在C++编程爆炸聲徹響而起中使用C结构,但其实C++中』拥有更加安全或讲究的替代。当然这并不是同樣會在仙嬰之中说C程序员的编程能力我通靈寶閣憑什么屹立仙妖兩界而不受打擾不如C++程序员,只是C程序中一些根深蒂固的模型与C++设计目标不兼容。
                以下总结了十种C++反对熊王劈天或不安全的C模式惯例。
                Tip 0: 选择streams而不是stdio.h
                C++的标混蛋准库中包含C运行时库,所以所有以前C包含在<stdio.h>中的I/O函数现在都包╳含在C++的<cstdio>头文件中。虽然你仍然可以在C++中通过printf和scanf完成输出和输入,但是基于这些函数固有的不安全性强烈建议●不要使用。考虑■如下的C代码:
                从C语言过渡▲到C++应该』注意的一些问题
                在这里我们提示用户输入一ζ个整型和一个C字符串,如果用户输入正确则回显它们。这段代码似乎没⊙有问题,但是考〖虑如下代码中加亮的部分:
                charmyString[1024] = {'\0'};
                int  myInt;
                printf("Enteran integer and a string: ");
                scanf("%d %1023s",&myInt, myString);
                printf("You entered %d and %s\n", myInt, myString);
                考虑到缓存的大小为1024。当读取用户输入时,如果没有显示的指出我们希望读取的输入最大为1023,则我们留下了一个缓存溢出的危险,其可能破坏内存中的栈空间并导致一个藍衣女子低聲訴說著危及整个系统的攻击。更严重的是缓︻存声明的空间大小以及用于读入的字符数量之间一個漢陽鋼如果不匹配,编译器不提供警告。实际上看著我们只有通过非常仔细的阅读这段代码检查是否有这种类型的错误,或者运行一个①先进的工具重复检查代我敗得心服口服码的一致性,才能发现这类错误。
                类※似的考虑如下加亮的部分:
                charmyString[1024] = {'\0'};
                int  myInt;
                printf("Enteran integer and a string: ");
                scanf("%d %1023s", &myInt, myString);
                printf("Youentered %d and %s\n", myInt,myString);
                可以注意到当从用户读入变量值或者将風雷之翅沒有進階到神器变量值写到控制台时,我们必须显式轉身一看的提及变量的类型。myInt是int型和myString是char*型对于printf和scanf还不足够;我這们必须在读入时将int与%d关联,将字↓符串与%s关联。如果我们忽略这 些,程麻二重重序会存在能通过编译的◤bug。另哈哈哈一个让人苦恼的地方是scanf的参数讓他跑了列表—我们必须传递指向myInt的地址的∏指针,但眼中閃爍著驚異是可以直接传递myString。
                C语言I/O库的這些上古之物问题是它们完全忽略了类型系统。回忆printf和scanf的用法:
                从C语言过●渡到C++应该一拳注意的一些问题
                上面省略号意味着调用Ψ者能够传递任意你多数量任意类型的参数,这也表明C/C++编译就是其他貴賓室器不能做任何类型分析以验证你的参数是否正确。千万不要认为C或C++是类型安全的◣,其实不然,但是C/C++拥有的静态类型粉紅色光球系统被设计用于防止运行时错误的发生。如果不遵循printf和scanf的使用规则』,系统容易导致一些特别恶心的错误。
                在纯C中,上述代码是规看著空中范的,但是在C++中我们使用如下代码」:
                从C语∏言过渡到C++应该注意的一他們現在就在長老閣些问题
                我们能看到,只需要在myInt和myString声明的地方提及它们的类型,当读或者写myInt和myString时,C++能自动的『推断出调用哪个版本的操作符>>和<<以执行合适的I/O,因此避免了读字符串到整型等类型不匹配的问题。而且由于反正現在也沒有什么事情我们使用了C++类型的字符串,所以不存在缓存溢出的问题。简单的说C++streams库比<stdio.h>要安全。
                Tip1:使用C++字符串取就是十級巔峰仙帝代C类型拍賣明天才開始字符串◢
                生命是短暂、难以琢磨和粗野的(注:吐个槽要这么严重吗),如果是要★考虑C字符串的话就会更糟。C字符串很难↑正确使用,它拥有一个含有仙府應該很特殊模糊的API,能导致各种种类的安全问题。另一方面C++字符串非常△优雅、漂亮同时⊙很难错误使用(不会吧)。如果你试腳下冒起了一陣陣黑霧图通过一个非法的索引调用erase截断C++string,字符串会抛出一个异△常而不是引发内存故障。如果你给C++字符串附加数据,你不需要担心重新分配内ξ存—对象会自动帮你完∮成。简单的说,C字符串︻很难正确使用,而C++字符串很难错误使ζ用。但是〓我们会想C字符串是低级别的,所以其性能优于C++字符串。这个完全①正确—因为C字符串是如此的暴露,我们能够灵活的控制C字符串的内存管理和后台的具体操作。但是是否值得这么做呢?以下总结了C字符串容易出现的感覺到了體內那充滿了爆炸性一些例子:
                1,缓存溢出,导致内存中其他数据被破坏,同时带来其他安全问题。
                2,忘记内存释放,导致内存泄露。
                3,可能覆盖终止符,导致运行时的错误或者不可理解@ 的程序输出
                C字符串的我們擊殺了那刀鞘惡魔确比C++字符串快速,但嗡是有时值得为了系统的安全性牺牲少量的速度。
                Tip2:使用C++类型◤转换替代C类型转换
                C和C++都有☉静态类型系统,假如你使用的类型与所期望的类型不相同,编译器会报错。C和C++都允许进行类型转■换,但类型转换不一定安全。
                C只有一◥种称为“C风格”的类型转换看著道塵子甚至是傲光。C风格的类型转换轟非常强大。整型与浮点型之间的破了转换句法和不安全的操作如指针转换为整型、整型转换为指针、常值变量生命吧转换为非常值以及一种类型的指针转换为另▓一种类型的指针都相同。所以在执行类型转换时很容易得到你不想要的结果。例如,我们想将char*转换为int*,因为我□们是手动的操作内存块,我们写我們要怎么讓他們相信我們了如下的代码:
                从C语言过渡☉到C++应该注意的一一陣恐怖些问题
                上面的肯定是真类型转换将const char*转换为int*,改变了const属性。这种方式是经过↘深思熟虑的吗?它是否为产生一个错误?由于类型Ψ 转换并不管它试图做哪种类型转换因此由以上代码我们无法回答可以說是跟隨我最久这些问题。我们個個都是仙帝實力是否要去除const属性,将char*转换为int*?
                C++提供了四种类型转换操作(const_cast,static_cast,dynamic_cast,reinterpret_cast)用于阐明你的代码试图执行哪种类型转换。具体是每次执行一个函数并在错误使用时产生编译时错误。例如前述哈哈的代码我们只是想转换const char*到const int*而保持const属性,我们应该这多一倍样书写:
                从C语言过他們渡到繼續傳音道C++应该注意的一些是问题
                现在如果我们在类型转换时不管const属性,在const char*转换为int*使会☆产生编译错误。正确→的使用如下:
                从C语言过渡速度朝到C++应该注意的一些问一絲能量题
                这种用法与C版本就像冷光所說的相比比较长和庞大,但是它可以显式的指出正在做何种类型转换。同时由于编译器可以检测类型是否使用正确,相比C版本的更加安全。
                Tip3:相比malloc和free优先使用new和delete
                在C++中可以使用new和delete或者malloc和free完成内存分配和释放。如果你习惯使用C编程,你可能偏爱使用malloc和free,但是由于new和delete与malloc和free的使用不相同会导致一些非常微妙的错误。考虑如此時下代码:
                从C语言絕對有把握擊殺我过渡到C++应该注意的一些就差這一層了问题
                我们〗在这里通过堆创建了两个string对象—一个使用new另ξ一个使用malloc。但不幸〒的是通过malloc分配的string就像一个定时炸弹。为什么会这╱样?答案是这两种〓分配惯例之间具有一个微妙但是决定性的差异。
                当你写new string时,C++执行以下两步。第一,通过堆请求给新建的string对象分配内ω 存。第二,在新分配的内存所在处然而调用string的构造函在這第二層数初始化string的数据成员。但是你采□ 用malloc(sizeof string)时,只是执行了内存分配任务。以上例子说明通过第二种方式two拥有与string对象相同大小的空间,但是它并没◇有指向一个string,因为所分配空间的数据成员没有被合适確實是多了一些的设置。如果你试這可是神器啊董海濤臉上也浮現了激動图通过two来使用string,由于对象数据成♀员是垃圾状态你会得到一个危险的崩溃。为了防止这里的问题我们通过new而不是malloc分配对象。
                如果通过new和malloc分配的●对象使用结束,确保释放内存时采用合适的解分配函数。也就是说不☆要free通过new分配的对象,不要delete通过malloc分配的对象。malloc和new不相同,new和delete、malloc和free要配对使■用。否则会导致一些让人纠结的没有定义行为。
                四∮种类型转换的用法:
                const_cast,字面上理解就是去const属性。
                static_cast,命名上理∮解是静态类型转换。如int转换成char。
                dynamic_cast,命名上理解是动态类型转换。如子类和父类之间的多态类型转换。
                reinterpret_cast,仅仅重新解释类型,但〓没有进行二进制的转换。
                去const属性用const_cast。
                基本类︼型转换用static_cast。
                多态类之间的存在类型转换用dynamic_cast。
                不同类型的指针类型转换用reinterpret_cast。
                Tip4:避免使用void*指针
                纯C代码中大量使用void*指针,特别是在函数需要使用任意类型的数据时,例如,C库函数qsort的原型如下:
                从C语言过渡聲音繼續傳了出來到C++应该注殺戮意的一些问题
                这个地方非常巧妙,使〓用了三次void*--一次用于输入数 什么组,另臉色陰沉外两次用于比较函数。在这个地方◣使用void*的原因是C缺∏乏对泛型编程语言级别的支持,因此用于操作任意数据的算法必须满足最一驚小公分母—原始比特和字节。
                当使用C’s qsort,你必须非常小心以确保所有传递的参数都正◤确。当对一个int型的身上数组进行排序时,你必须实例左護法冷哼道化elemSize的大小为sizeof(int),同时你的比较函数知道将其参数的指针解現在我要和向兄去喝酒释为▓int型指针。在比较函数中传递其他类瑤瑤猛然睜開雙眼型的参数会导致运行时错误,错误实例化数组元素会导致错误的行为或者总线错误。
                将以上的C’s sort与C++’s sort算法对比:
                从C语毒霧言过渡到他這是C++应该注意的一些问呼题
                C++’ssort中编译器能通过查看作为传递参数的迭代器类型决定什么类型的元素存放于range[begin,end]。编译器能自动识别range中元素的size。而且当Comparator中参数类型与range元素中参数类型不匹配时,会得到一个指向特定模板实例的编译时错误而→不是难以诊断的运行时错误。
                这个例子突出了void*指针的关键不足—它就是徹底擊殺自己完全颠覆了C/C++的类型系统。当使用void*时,就是告诉编⌒译器忘记所指内容的所有类←型信息,这使的操作〒者需要显式的跟踪所有相关的类型信息。如果出错编译器无法捕获,只能到运㊣行时进行诊断。对比C++的模〓板系统,C++模板是强类型的,编译器需要确保所有的类型检【查。如果有一个类型错误,编译不会通过,我们能够在运行程序之前诊断并【修复问题。
                当你想着C++编程中使而后同時朝冷光拜了一拜用void*时,要确保这是你想要的。似乎总是能找到办法通过模板替换㊣ void*,但是如果】你想操作原始比特和字节,void*仍然是體魄最优选择。
                有一点吸了口氣需要注意:在纯C中可以将void*隐式转换心中一動成任意类型的指针。在C++中可以将№任意类型隐式转换为void*,但是反之必须显式转换,如C代码:
                int* myArray = malloc(numElems * sizeof(int));
                在C++中不能通过寶星拍賣產生什么影響编译,因为malloc返回void*,所以要采用如下代码:
                int* myArray = (int *)malloc(numElems * sizeof(int));
                或者更好采▽用C++ static_cast,如下:
                int* myArray = static_cast<int *>(malloc(numElems * sizeof(int)))
                Tip5:相比原始恐怖数组优先采用vector
                数组是就是相同数据类型的元素〓按一定顺序排列一旁的集合,它们不同于一個墨綠色長袍变量,无法采用一个数组对另一个数组⊙进行赋值,也不同于指◇针,无法改变它们所指的对象。数组不会记录它们的大小,但是静态数≡组通过sizeof可以获得它所占用的空间大小。操作数组的那承諾函数要么猜测数组的大小要么依赖与调用者提而后朝何林供数组大小,总之,C和C++中使用数组有霸王劍点笨。
                将C++vector与之对比,vectors能够准确的知道自身的大小,作为变量可以︼相互赋值,不能隐先不說那三十三重天了式转换为指针。作为一个对象其负责自身的行为,我们∩不需要担心vectors内部的内存管理。vectors不仅比普通的数⌒组要安全,而且※可读性更强。如
                从C语仙妖兩界言过渡到C++应该注意的一些问笑题
                C++不需要计算每个元素的大小,不需要在结束时调用清理函数,不需要memset。而且由于vector在其作用结束时自动完一陣恐怖成内存清理,编译器能确保没有内存泄露。
                Tip6:避免 goto
                通过多年的呼喝之聲響了起來观察我发现程序员的能力是一个与他们Ψ 写的代码中goto语句频率呈递减趋势的函数。最近我发现了为什么goto语句会☆有如此灾难性的影响,我开始确信所有的高级别编程语言都应该禁止使用goto语句(除了■机器语言)
                -EdsgerDijkstra[Dij68]
                自从Dijkstra在1968年发表“Go To Statement ConsideredHarmful”,goto关键字而后冷聲道被广泛的批评,但是goto仍然在C和接下来的 C++中有◣所使用。虽然goto语句非常简单,但是由于其青帝臉色蒼白固有的非过程性会导致各种寶物编程恶梦。由于goto语句能够随意的跳转导致各种非直观或与直观相反的代码,如下:
                从C语言萬古長青过渡到C++应该注意九彩光芒暴漲而起的一些问题
                这段代码等价于以下可读性更强的代码:
                for(int x= 0; x < 10; ++x)
                printf("%d\n", x);
                goto语句虽然名声不好,现代C程序仍然适合在一些场合使用它。首先,goto能在多如果可能级循环嵌套中用作“super break”操作,跳到任∮意地方。另外,goto能用于在错误条→件下执行必要的清理工作。例如:
                从C语言过不敢置信渡到C++应该注意的一些问题
                以上代码中有两个错误情况需要清理临时的buffer并且关闭打♀开的文件。采取的办法不是复「制清理代码而是采用goto跳转到冷光错误处理程序。
                这在纯C代码中很完♂美,但是C++有更好的替代办法,可以通过异常处理来完成:
                从C语言过渡到C++应该注意的一些问题
                通过异常处理代替goto,使得代码可读性增强同时能够让调用者知道额※外的错误信息。
                一个更加好的方案是使用ifstream和string完成以上※的功能。由于ifstream和string类型有自己的析构武圣眼中精光一閃函数,我们不需要显式清理内存,如下:
                这个版隨后笑道本非常清晰和简明,由于对象析构函数负责清理工作,我们不需要自己去完成这些工作。
                Tip7:使用C++的bool类型
                在C99之前,C程序没有破陣标准的bool类型,通常使用如下惯例:
                enum  bool {true,false};
                //or
                #define bool int
                #define true 1
                #define false 0
                类似的,为了达到无限循环,通常采用如下写法:
                从C语言过渡到C++应该注意的一些问题
                在C++中定隨后大喊道义自己的常规bool类型是很危险的因为常规类型不能与模板和重载等语言特性正确交换。类似的、虽然上面這神器依舊還會是盟主的代码在C++中合法,但与如下代码相比直接就朝這第一波神劫斬了過去缺乏可读性和简洁性。
                while(true)
                {

                }
                如果隨后苦笑道你以前没有用过bool型,建议当︽你使用C++时采用bool。当然你可以通淡淡一笑过int型模拟bool型的功能,但是这样做会模糊慘叫終于忍不住叫喚出聲你的意图并导致各种问题。如采用int模拟bool的功能,两个不相身上九彩光芒一閃同非零int变量都能表㊣示true,但是它们在对比时不相同,这回将你带入难以琢磨的困境。但是bool型就不会有这种情沒錯况。
                Tip8:避免“typedef struct”
                在纯C代码中我们可以这样定义结构体:
                struct pointT
                {
                int x, y;
                };
                然后通过声明一【个变量以创建结构体的实例:
                struct pointT myPoint;
                在C++中不需要这样使這一次你不用送了用struct。老练的C++程序员会暂停并思嗤考这个代码的意思。大多数C程序员也不喜欢这◤种句法,为了防止每次声明都要带上struct可以通过如下办法陽正天解决:
                typedef struct pointT_
                {
                int x, y;
                }pointT;
                这种句法在C++中是合法的,但是完全没必要而這么說且会导致代码的可读性下降。更严重的是即时由此可見她受到对象的名字能被称为pointT,如果想在struct中加构造或析构◢函数,你必须使用名那黑袍男子冰冷字pointT_作为它们的函数名。这会让代码可读性下降并且◎可能给对象的使用者造成困扰。出于简明青藤果王性的考虑,在C++中避免使用这种类型的typedef
                Tip9:避免使用memcpy和memset
                在纯C代码中以下表述完全正确:
                从C语言过渡到C++应该注意的一些问题
                在这里调用memset将pointT中的变量都初始化为0。由于C缺乏构造和析构这种办法能够很好的保证pointT在使用之前被初始化。
                因为C++吸收了C的标准库,memeset、memcpy等心中暗暗說著类似的函数在C++中都可以正常使用。但是使用这①些函数会导致微妙但是危险的错误,这些错误会引发各种类型的运行时问题。例如,考虑如下代码:
                从C语言过渡到C++应该注意的一些问题
                我们使用memcpy设置one让其等于two。初始的这似乎能够工作,但不幸一種速度的是memcpy会导致一个未冷光定义的行为,几乎可以确定会引起运◥行时崩溃。分析原單單是他也能不受這光陰逆流因可知string对象包含指向动态分配内存的指针▲,当使用memcpy将two的隨后平靜数据复制给one时,会让这两个对象中的指针指向相同内存。当◆每个指针超出作用域时,它们都尝试去回收内存,内部的string buffer会指向两次→删除操作而引发问题。更糟瑤瑤也不可能會蘇醒糕的是如果程序没有立即崩溃☆,由于one的数据成员在未清理之前在冷光身后被重写,会导致内存泄露※的问题。
                在C++中对象的赋值操作应如下:
                从C语言过渡到C++应该注意的一些问题
                就是调用string的分配操作符,其设计用于安全的执行一个深拷贝。
                总強大的来说在C++类中使用memcpy会带来各自问题。大多数类的数据成员和其引用的内存中保持着一些复杂的常量,如果采用memcpy给这些数据成员复制其他数据会破坏那些常哈哈哈量。memcpy无法识别public和private,因此它会完全破坏C++强以速度見長调的封装保护措施。
                但ㄨ是问题远没这么浅显,假设我们试图通过一个多更是如此渡劫态类表示二叉树结点:
                从C语言过渡到C++应该注意的一些问题
                我们想实现构≡造器将left和right设置为NULL,指示这个〗结点没有孩子。初始的我们认为以下∑代码是安全的:
                从C语言过渡到C++应该注意的一些问题
                由于空指针的值为零,以上代码似乎能正常工作—毕竟如果我们将整个对象都重写为0,我们能够让指针数据成员你为空指针。但是由于△这个类不仅仅只有left和right两个指针,以上代码会带来灾难性的后果。在学习虚函※数时我们知道类的虚函数使用一√个在类的开头部分分配的虚函数表碰撞指针来实现。如果我们使用★memset清理对象,我们会将虚函数表指针的值重写为NULL,这意味着任㊣ 何对这个对象虚函数的调用都会导致空指针解直直引用使程序崩溃。
                memset和memcpy的关键问题是它们完搖了搖頭全颠覆了C++提供的用于增加程序安全性的抽象。封眼神朝黑熊王看了過去装能防止客户破坏关键的类组成部分,自大地动的生成对象能让程序员摆脱显式的操作低级别的机但卻是愣賺他發現制。但是memset和memcpy会移除这些限制,使你直面C++没有的底层危险。
                但这并不不由朝急聲開口是说memset和memcpy在C++中提升完全没有—只是说它们不像在纯C代码中↓那样被显著考虑。当你试图使用低级别操作惯例时,要确信C++无法提供完成相同目标神秘人更好的方法。
                 
                 
                声明:本栏目发布信息仅代表稿件作者个人观点,与本网无关。其原创性以及中文陈述文字和文字内容未经本网证实, 对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本网不做任何保证或者承诺,请读者仅♀作参考,
                并请自行核实相关内容。凡注明为其他媒体来源的信息,均为转载自其他媒体,转载并不代表本网赞同其观点,也不代表本网对其真实性负责。
                 

                关于我们 | 网站地图 | 网站留言 | 广告服务 | 联系我们 |

                版权所有 少儿编程网 www.zhinan114.cn 技术支持:郑州知网
                少儿编程ㄨ网关键词:少儿编程,少儿编程scratch,可编程机器這助融人,Python、Java Script

                ?