﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Daywei0123-随笔分类-C/C++</title><link>http://www.cppblog.com/Daywei0123/category/20847.html</link><description>技术追求卓越 梦想创造未来</description><language>zh-cn</language><lastBuildDate>Sun, 11 Sep 2016 16:29:58 GMT</lastBuildDate><pubDate>Sun, 11 Sep 2016 16:29:58 GMT</pubDate><ttl>60</ttl><item><title>SDL认识</title><link>http://www.cppblog.com/Daywei0123/archive/2016/06/28/213813.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Mon, 27 Jun 2016 16:17:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2016/06/28/213813.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/213813.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2016/06/28/213813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/213813.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/213813.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; SDL是一个轻量级的，用C语言开发的多媒体库。它包含了图像绘制、文字绘制、事件处理、声音播放等模块。因为SDL的易用以及它的扩展库的完整性，很多2D游戏都使用SDL开发，其中就包括这几年大热的移动平台上的游戏《愤怒的小鸟》。<br /><br />然后说说从个人角度上看SDL的特点。<br /><br /><strong>1.跨平台。</strong>确确实实是跨了N个平台，甚至包括NDS这种平台。有了SDL，你甚至可以在windows、linux、Android上任意移植你的游戏。当然，前提是你目标平台的编译器认识你的代码(￣&#9661;￣)&#8221;。有了SDL泥甚至可以只用c语言开发安卓游戏哟。<br /><br /><strong>2.开源。</strong><br /><br /><strong>3.SDL2.0绘图效率很高</strong>。事实上相较之SDL1.2我个人比较喜欢SDL2.0的原因也是在此。个人感觉（其实我没看过源码）SDL1.2应该是个跟当年的DirectDraw差不多的东西，像素填充什么的，有相当程度上是要磨CPU的。而SDL2.0从绘图方式上就革新了，抛弃了之前的surface与clip的模式，把实际绘制的东西改为了Texture，而把之前的surface改为了创建Texture的一个临时环节。而texure，顾名思义，其实就是DirectX、OpenGL这些底层的3D硬件加速API的贴图。<br /><br />当下DirectX、OpenGL标准下的显卡的渲染管线无非就是：1.把顶点（可以理解成坐标）传给显卡 。2.把texture传给显卡。 3.告诉显卡怎么处理这些数据（shader）。 4.显卡把东西给你显示出来。而基于DirectX、OpenGL(移动平台是OpenGL ES)的SDL2.0，正是恰好地利用了当下显卡的能力。<br /><br /><strong>4.SDL可以用作3D图像引擎和底层DirectX/OpenGL API的中间层</strong>。当然，其实如果把SDL这样用的话，那就真是很薄的一层了：）<br /><br /><strong>5.易用</strong>。这是相对而言的，比如在windows上，你用了SDL这个库之后，基本就不用去理会Windows那些又臭又长用不着的参数又多的API了。我不是在讨论信仰问题也不是要诋毁windows，我是在客观陈述windows api那个要初始化一个窗口必须要堆100行代码的设定实在是打击初学者积极性的事实。<br /><br /><span style="white-space: normal; word-spacing: 0px; text-transform: none; float: none; color: rgb(155,171,177); text-align: left; font: 16px/28px 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53; widows: 1; display: inline !important; letter-spacing: normal; background-color: rgb(47,48,60); text-indent: 32px; -webkit-text-stroke-width: 0px">SDL_image、SDL_ttf、SDL_mixer、SDL_net 外部扩展库，也是不错的选择。</span><br /><br />性能没有测试，仅从写代码角度上来说，个人感觉2.0将操作给弄得复杂了。<br /><br />1.2---------------------------------------<br />只有SDL_Surface的概念，屏幕是surface，图片，文字等都是surface，<br />只要将准备好的各种图片，贴到屏幕里去(SDL_BlitSurface)；再刷一下屏幕(SDL_Flip全局的、或SDL_UpdateRect局部的)就ok了。。。<br /><br />SDL_Init(SDL_INIT_EVERYTHING);<br /><br />SDL_Surface* screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);<br />SDL_Surface* bmp = SDL_LoadBMP("back.bmp");<br />SDL_BlitSurface(bmp, 0, screen, 0);<br />SDL_Flip(screen);<br /><br />while(SDL_WaitEvent(&amp;e)) {<br />switch(e.type) {<br />case SDL_QUIT:<br />return;<br />}<br />}<br />SDL_Quit();<br />2.0---------------------------------------<br />整出了SDL_Window,SDL_Renderer,SDL_Texture新的3个东西。<br />并且我要画一张图，先要得到surface，然后转换为texture，再临时贴到renderer，最后才刷屏。<br /><br />SDL_Init(SDL_INIT_EVERYTHING);<br /><br />SDL_Window* window = SDL_CreateWindow("hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);<br />SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);<br />SDL_Surface* surface = SDL_LoadBMP("back.bmp");<br />SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);<br />SDL_RenderClear(renderer);<br />SDL_RenderCopy(renderer, texture, 0, 0);<br />SDL_RenderPresent(renderer);<br /><br />while(SDL_WaitEvent(&amp;e)) {<br />switch(e.type) {<br />case SDL_QUIT:<br />return;<br />}<br />}<br />SDL_Quit();<br /><br />其实，我真心不觉得提出SDL_Window,SDL_Renderer,SDL_Texture这些概念先进性在哪里？可能是与openGL的概念保持一致吧。<br />而且从维护的角度出发，不管sdl2.0性能提升了多少，如果接口本身不需要改动，不是更加好么？<br /><br />---------------------------------------------<br />最后我发现，同样是渲染的窗口<br />1.2用SDL_Flip(screen);之后被其他窗口挡住之后，回来画面还是在的；<br />2.0用SDL_RenderPresent(renderer);之后被其他窗口挡住之后，回来画面就不在了； <img src ="http://www.cppblog.com/Daywei0123/aggbug/213813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2016-06-28 00:17 <a href="http://www.cppblog.com/Daywei0123/archive/2016/06/28/213813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Exceptional C++ 读书笔记2</title><link>http://www.cppblog.com/Daywei0123/archive/2014/08/22/208095.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Fri, 22 Aug 2014 07:00:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/08/22/208095.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/208095.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/08/22/208095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/208095.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/208095.html</trackback:ping><description><![CDATA[永远不要用#include包含不必要的头文件<br /><br />如果只需要流的前置声明，应该优先使用#include&lt;iosfwd&gt;<br /><br />只需要前置声明时，绝不要用#include包含相应的头文件。<br /><br />如果使用聚合关系就已经足够，就不要使用继承。<br /><br />要避免使用内联或者复杂的调整方法，除非通过性能分析证明这确实是必要的。<br /><br />正确使用名字空间。如果将一个类放入名字空间，那么同时要保证将这个类的所有辅助函数和运算符函数也放入相同的名字空间。否则，你将在代码中发现奇怪的结果。<img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/daywei0123/内存区域.jpg" width="1708" longdesc="" height="2000" /><br />要理解这五种不同类型的内存，了解他们为什么是不同的，以及他们各自的行为又是怎么样：栈（自动变量）、自由存储（new/delete）、堆（malloc/free）、全局（静态变量、全局变量、文件作用域变量等）、常量数据（字符串常量等）。<br /><br />优先使用自由存储（new/delete），避免使用堆（malloc/free）。<br /><br />对于&#8220;堆&#8221;和&#8220;自由存储&#8221;进行区分，这一点很重要，因为在C++标准中有意避开了这两种类型的内存是不是相关的这个问题。例如，当通过：：operator delete()函数来释放内存时，在C++标准的18.4.1.1中，最后一项是这样的：<br />&#8220; 在C++标准中并没有规定，在哪些情况下，在通过operator delete回收的存储空间中，有一部分或者全部的控件可以再随后调用operator new或者calloc，malloc以及realloc等函数时被重新分配，这些函数的声明时在&lt;cstdlib&gt;中。&#8221;<br />而且，在C++标准中也没有规定，new/delete是否需要通过malloc/free来实现。不过，在C++标准20.4.6节的第3段和第4段中规定了，malloc/free一定不能使用new/delete来实现：&#8220;calloc、malloc和realloc函数不会通过调用::operator new()来分配存储空间。函数free（）不会通过调用::operator delete() 来释放内存。&#8221;<br /><br />如果在类中定义了new和delete中的任意一个运算符函数，那么一定要同时定义另外一个。<br /><br />通常应该显式地将函数operator new ()和operator delete()声明为静态函数。他们永远都不能使非静态成员函数。<br /><br />永远都不要通过多态的方式处理数组。<br /><br />优先选择使用vector或者deque，而不是数组。<br /><br />在编写拷贝赋值运算符函数时，永远都不要指望能够通过对自我赋值进行检测来保证函数的正确性；应该在拷贝赋值运算符函数中使用&#8220;创建临时对象并进行交换&#8221;的惯用法，这种方法不仅是异常安全的，而且在处理自我赋值时也是安全的。<br /><br />可以将自我赋值检测作为一种优化手段，以避免不必要的工作，这是正确地做法。<br /><br />不仅要避免编写类型转换运算符函数，而且还要避免编写隐式的构造函数。<br /><br />尽量编写异常安全的代码。在编写代码时应该始终遵循：即使在出现异常时，资源仍然能够被正确地释放，并且数据也总是处于一致的状态。<br /><br />避免使用语言中那些不常用的特性，而应该使用最简单并且有效的技术。<br /><br />拷贝初始化过程绝不是赋值过程，因此在初始化中永远都不会调用函数T::operator=()。是的，我知道在初始化语句中有一个&#8220;=&#8221;符合，但不要被它迷惑。它只是从C语言中沿用过来的一种语法，并不代表赋值运算。<br /><br />如果可能的话，优先使用&#8220;T t(u);&#8221;这种形式，而不是&#8220;T t=u;&#8221;的形式。通常，能能够时候后者的地方，都可以使用前者，并且使用前者还有更多的好处&#8212;&#8212;例如，可以带多个参数。<br /><br />在函数声明中，如果参数是以传值方式来传递的，则不要使用const。而如果在这个函数的定义中，参数是不能被修改的，那么应该使用const。<br /><br />对于不是内置类型的返回值来说，当使用返回值的方式而不是返回引用的方式时，应该优先选择返回const值。<br /><br />const 和mutable都是你的朋友<br /><br />优先使用新形式的类型转换。<br /><br />不要通过类型转换去掉常量属性，而应该使用mutable。<br /><br />避免使用向下的类型转换。<br /><br />优先通过引用方式来传递对象参数，而不是传值方式，并且在所有可能的地方都使用const。<br /><br />避免使用内联，除非从性能的分析上来看确实有必要这么做。<br /><br />避免使用全局变量或者静态变量。如果必须使用，那么一定要特别注意这些变量的初始化顺序。<br /><br />在构造函数的初始化列表中，应该把 基类按照他们在类定义中出现的先后顺序进行排列。<br /><br />在编写代码时，永远都不应该依赖函数参数的求值顺序<img src ="http://www.cppblog.com/Daywei0123/aggbug/208095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-08-22 15:00 <a href="http://www.cppblog.com/Daywei0123/archive/2014/08/22/208095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Exceptional C++ 读书笔记1</title><link>http://www.cppblog.com/Daywei0123/archive/2014/08/22/208093.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Fri, 22 Aug 2014 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/08/22/208093.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/208093.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/08/22/208093.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/208093.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/208093.html</trackback:ping><description><![CDATA[<p>绝对不要对无效的迭代器执行解引用（dereference）操作<br /><br />用于不要将异常安全性放在事后考虑。异常安全性会影响到类的设计。它永远都不会&#8220;只是一个实现细节&#8221;。<br /><br />在传递对象参数时，选择const&amp;方式而不是传值方式。<br /><br />对于程序运行中不会改变的值，应该预先计算并保存起来备用，而不是重复地创建对象，这是没有必要的。<br /><br />通常，为了保持一致性，应该使用前置递增来实现后置递增，否则，当其他用户在使用你的类时，可能会得到奇怪结果。<br /><br />优先选择使用前置递增。只有在需要初始值时，才使用后置递增。<br /><br />在进行隐式类型转换时，要注意在转换过程中创建的 临时对象。要避免这个问题，一个好办法就是尽可能地通过显式的方式来构造对象，并避免编写类型转换运算符。<br /><br />记住对象的生存期。永远，永远，永远都不要返回指向局部对象的指针或引用；它们没有任何用处，因为主调代码无法跟踪它们的有效性，但却可能会试图这么做。<br /><br />尽可能地重用代码&#8212;&#8212;尤其是标准库中的代码&#8212;&#8212;而不是自己去编写代码，这样更快、更容易，也更安全。<br /><br />如果在函数中不打算处理所抛出的异常，那么应该将异常转发给能够进行处理的上层调用者。<br /><br />在编写代码时应该始终遵循：即使在出现异常时，资源仍然能够被正确地释放，并且数据也总是处于一致的状态。<br /><br />遵循标准的异常安全规则：永远不要在析构函数、重载运算符函数operator delete()或者operator delete[]()中抛出异常； 在编写每个析构函数和内存释放函数时，要假设存在着&#8220;throw()&#8221;这样的异常规范。<br /><br />遵循标准的异常安全性规则：在每个函数中，要将所有可能会抛出异常的代码单独放在一起，并且对这些代码进行安全处理。然后，当你确认这些代码执行的工作都已经成功地完成时，才可以使用不会抛出异常的操作来修改程序的状态。<br /><br />永远都不要到最后才实现异常安全性。异常安全性会对类的设计产生影响。它永远都不会&#8220;只是一个实现细节&#8221;。<br /><br />优先考虑实现内聚。要努力使每段代码&#8212;&#8212;每个模块、每个类、每个函数&#8212;&#8212;都只有单一的，并且是明确定义的功能。<br /><br />&#8220;异常不安全&#8221;总是与&#8220;拙劣的设计&#8221;结伴的。如果程序的设计逻辑清晰，那么即使有一段代码不是异常安全的，一般来说也不会有太大问题，并且可以很简单地进行修正。但如果有一段代码由于设计问题而不能被编写成异常安全的，我们通常都会认为这个设计时拙劣的。下面是两个拙劣设计的示例。<br />示例1：如果在一个函数中需要实现两个不同的功能，那么这个函数很难被编写成异常安全的。<br />示例2：如果在拷贝赋值运算符函数中必须对自我赋值进行检测，那么这个函数也可能不是完全异常安全的<br /><br />遵循标准的异常安全性规则：以&#8220;获得资源也就意味着初始化&#8221;这种模式来分离资源的所有权和资源的管理权。<br /><br />在进行设计中，要始终牢记重用性。<br /><br />优先采用&#8220; a op=b;&#8221;这种写法，而不是"a = a op b;"（这里的op表示某个运算符）。这种写法更为清晰，效率也高。<br /><br />如果定义了某个运算符（例如，operator+），那么通常还应该同时定义与这个运算符相对应的赋值运算符（例如，operator+=）。并且用后者来实现前者。而且，还应该维护op和op=之间的自然关系。<br /><br />在C++标准中规定：运算符=，（），[]和-&gt;必须被定义为成员函数，而在类中定义的new,new [],delete和delete[]等运算符函数必须是静态成员函数。对于其他的运算符函数：<br />&nbsp;&nbsp;&nbsp;&nbsp; 如果运算符函数是用于流I/O的opeator&gt;&gt;或者operator&lt;&lt;，或者如果运算符函数需要对其左操作数进行类型转换，或者运算符函数可以通过类的公有接口来实现，那么将这个函数定义为非成员函数（在前两种情况中，如果需要的话也可以被定义为友元函数）；如果运算符函数需要实现虚函数的行为，那么增加一个虚函数来提供虚函数的行为，并用这个虚成员函数来实现运算符函数否则将预算富函数定义为成员函数。<br /><br />在函数opeator&gt;&gt;和operator&lt;&lt;中应该始终返回对流对象的引用。<br /><br />将基类的析构函数定义为虚函数（除非你能保证，永远都不会有人通过指向基类的指针来删除派生类的对象）。<br /><br />如果在派生类中定义的函数与基类中的函数有相同的名字，并且你不想隐藏基类中函数，那么应通过using声明语句将基类的这个函数引入到派生类的作用域中。<br /><br />永远不要改变被覆盖的基类函数中的默认参数值。<br /><br />除了对真正的Liskov IS-A和WORKS-LIKE-A关系进行建模之外，永远都不要使用共有继承。所有被覆盖的成员函数不能超过实际需求的范围，同时也不能小于这个范围。<br /><br />使用公有继承的目的是重用代码（编写以多态的方式使用基类对象的代码），而重用（基类中的）代码并不一定要使用公有继承。<br /><br />对&#8220;is implemented in terms of&#8221;这种关系建模时，应该优先选择成员关系/包含的方式，而不是私有继承的方式。只有非用继承不可时，才应该使用私有继承&#8212;&#8212;也就是说，当需要访问保护成员或者需要覆盖虚函数时，才使用私有继承。永远都不要只是为了代码重用而使用共有继承。<br /><br />对于广泛使用的类，应该优先使用编译器防火墙这种惯用法（也叫做Pimpl惯用法）来隐藏实现细节，通过一个不透明的指针（指向一个进行了前置声明但又没有定义的类）来保存私有成员（包括状态变量和成员函数），声明这个指针时可采用&#8220;struct XxxxImpl* pImpl;XxxxImpl* pimpl_;&#8221;这样的形式。例如：&#8220;class map{ private :struct MapImpl;MapImpl* pimpl_;}&#8221;<br /><br />包含，也可以叫做&#8220;聚合&#8221;，&#8220;分层&#8221;，&#8220;HAS-A&#8221;或者&#8220;委托&#8221;。优先选择包含而不是继承，对于IS-IMPLEMENTED-IN-TERMS-OF这种关系建模时，应该优先考虑使用包含，而不是继承。<br /><br /></p><img src ="http://www.cppblog.com/Daywei0123/aggbug/208093.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-08-22 11:50 <a href="http://www.cppblog.com/Daywei0123/archive/2014/08/22/208093.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从缺陷中学习C/C++</title><link>http://www.cppblog.com/Daywei0123/archive/2014/07/24/207780.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Thu, 24 Jul 2014 07:29:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/07/24/207780.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/207780.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/07/24/207780.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/207780.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/207780.html</trackback:ping><description><![CDATA[<br /><span style="font-size: 18pt"><strong>有符号int与无符号int比较的后果</strong></span> 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" />unsigned&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;ud</span><span style="color: #000000">=</span><span style="color: #000000">1</span><span style="color: #000000">;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">(i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;ud)<br /><img id="Codehighlighter1_42_64_Open_Image" onclick="this.style.display='none'; Codehighlighter1_42_64_Open_Text.style.display='none'; Codehighlighter1_42_64_Closed_Image.style.display='inline'; Codehighlighter1_42_64_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_42_64_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_42_64_Closed_Text.style.display='none'; Codehighlighter1_42_64_Open_Image.style.display='inline'; Codehighlighter1_42_64_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_42_64_Closed_Text"><img alt="" src="http://www.cppblog.com/Images/dot.gif" /></span><span id="Codehighlighter1_42_64_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">true</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">else</span><span style="color: #000000"><br /><img id="Codehighlighter1_71_94_Open_Image" onclick="this.style.display='none'; Codehighlighter1_71_94_Open_Text.style.display='none'; Codehighlighter1_71_94_Closed_Image.style.display='inline'; Codehighlighter1_71_94_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_71_94_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_71_94_Closed_Text.style.display='none'; Codehighlighter1_71_94_Open_Image.style.display='inline'; Codehighlighter1_71_94_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_71_94_Closed_Text"><img alt="" src="http://www.cppblog.com/Images/dot.gif" /></span><span id="Codehighlighter1_71_94_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">false</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span></div>一看结果应该是打印出true，但事实却是false。<br />signed int 型变量被转换成unsigned int型变量。-1转换成unsigned int的结果是一个非常巨大的正整数（32位系统上是2的32次方-1），需要进行强转为int型。<br /><br /><strong style="font-size: 18pt">位域变量</strong><br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /> 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">struct</span><span style="color: #000000"> data<br /><img id="Codehighlighter1_12_48_Open_Image" onclick="this.style.display='none'; Codehighlighter1_12_48_Open_Text.style.display='none'; Codehighlighter1_12_48_Closed_Image.style.display='inline'; Codehighlighter1_12_48_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_12_48_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_12_48_Closed_Text.style.display='none'; Codehighlighter1_12_48_Open_Image.style.display='inline'; Codehighlighter1_12_48_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_12_48_Closed_Text"><img alt="" src="http://www.cppblog.com/Images/dot.gif" /></span><span id="Codehighlighter1_12_48_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" /> </span><span style="color: #0000ff">int</span><span style="color: #000000"> flag:</span><span style="color: #000000">1</span><span style="color: #000000">;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" /> </span><span style="color: #0000ff">int</span><span style="color: #000000"> other:</span><span style="color: #000000">31</span><span style="color: #000000">;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000">;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" />printf(</span><span style="color: #000000">"</span><span style="color: #000000">data size %d\n</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(data));<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" />data test1;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" />test.flag </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000">;<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">(test.flag </span><span style="color: #000000">==</span><span style="color: #000000">1</span><span style="color: #000000">)<br /><img id="Codehighlighter1_136_158_Open_Image" onclick="this.style.display='none'; Codehighlighter1_136_158_Open_Text.style.display='none'; Codehighlighter1_136_158_Closed_Image.style.display='inline'; Codehighlighter1_136_158_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_136_158_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_136_158_Closed_Text.style.display='none'; Codehighlighter1_136_158_Open_Image.style.display='inline'; Codehighlighter1_136_158_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_136_158_Closed_Text"><img alt="" src="http://www.cppblog.com/Images/dot.gif" /></span><span id="Codehighlighter1_136_158_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" /> printf(</span><span style="color: #000000">"</span><span style="color: #000000">true</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span><span style="color: #000000"><br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">else</span><span style="color: #000000"><br /><img id="Codehighlighter1_165_188_Open_Image" onclick="this.style.display='none'; Codehighlighter1_165_188_Open_Text.style.display='none'; Codehighlighter1_165_188_Closed_Image.style.display='inline'; Codehighlighter1_165_188_Closed_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif"><img style="display: none" id="Codehighlighter1_165_188_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_165_188_Closed_Text.style.display='none'; Codehighlighter1_165_188_Open_Image.style.display='inline'; Codehighlighter1_165_188_Open_Text.style.display='inline';" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif"></span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_165_188_Closed_Text"><img alt="" src="http://www.cppblog.com/Images/dot.gif" /></span><span id="Codehighlighter1_165_188_Open_Text"><span style="color: #000000">{<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" /> printf(</span><span style="color: #000000">"</span><span style="color: #000000">false</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><img alt="" align="top" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" />}</span></span></div>int的位域变量，而用一个bit表示int时，这一位是用来表示有符号位的，带符号的一个bit的位域变量的取值范围是0或-1.无符号的一个bit的位域变量的取值范围是0或1，故1赋给flag时会出现溢出，flag变为-1. <br />Reference：<a href="http://wenku.baidu.com/view/670eff4bf7ec4afe04a1dfd7.html">http://wenku.baidu.com/view/670eff4bf7ec4afe04a1dfd7.html</a><img src ="http://www.cppblog.com/Daywei0123/aggbug/207780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-07-24 15:29 <a href="http://www.cppblog.com/Daywei0123/archive/2014/07/24/207780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective STL(5)——算法</title><link>http://www.cppblog.com/Daywei0123/archive/2014/06/25/207410.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Wed, 25 Jun 2014 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/06/25/207410.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/207410.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/06/25/207410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/207410.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/207410.html</trackback:ping><description><![CDATA[<div><span style="font-size: 18pt">1.确保目标空间足够大<br /></span><br /><span style="font-size: 18pt">2.了解各种与排序有关的选择</span><br /><span style="font-size: 18pt">&nbsp;&nbsp;</span><span style="font-size: 14pt">如果需要对vector、string、deque或者数组中的元素执行一次完全排序，那么可以使用sort或者stable_sort。</span><br /><span style="font-size: 14pt">&nbsp; 如果有一个vector、string、deque或者数组，并且只需要对等价性最前面的n个元素进行排序，那么可以使用partial_sort。</span><br /><span style="font-size: 14pt">&nbsp; 如果有一个vector、string、deque或者数组，并且需要找到第n个位置上的元素，或者，需要找到等价性最前面的n个元素但又不必对这n个元素进行排序，那么，nth_element正是你所需要的函数。</span><br /><span style="font-size: 14pt">&nbsp; 如果需要将一个标准序列容器中的元素按照是否满足某个特定的条件区分开来，那么，partition和stable_partition可能正是你所需要的。</span><br /><span style="font-size: 14pt">&nbsp; 如果你的数据在一个list中，那么你仍然可以直接调用partition和stable_partition算法；可以用list::sort来替代sort和stable_sort算法。但是，如果你需要获得partial_sort或nth_element算法的效果，那么，正如前面我所提到的那样，你可以有一些简洁的途径来完成这项任务。<br /></span><br /><span style="font-size: 18pt">3。如果确实需要删除元素，则需要在remove这一类算法之后调用erase。<br /></span><br /><span style="font-size: 18pt">&nbsp;&nbsp; </span><span style="font-size: 14pt">remove不是真正意义上的删除，因为它做不到。<br /></span><br /><span style="font-size: 18pt">4.对包含指针的容器使用remove这一类算法时要特别小心。会导致资源泄露。<br /></span><br /><span style="font-size: 18pt">5.了解哪些算法要求使用排序的区间作为参数。<br /></span><br /><span style="font-size: 18pt">6.通过mismatch或lexicographical_compare实现简单地忽略大小写的字符串比较<br /></span><br /><span style="font-size: 18pt">7.理解copy_if算法的正确实现<br /></span><br /><span style="font-size: 18pt">8.使用accumlate或者for_each进行区间统计。</span></div><img src ="http://www.cppblog.com/Daywei0123/aggbug/207410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-06-25 17:06 <a href="http://www.cppblog.com/Daywei0123/archive/2014/06/25/207410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective STL(4)——迭代器</title><link>http://www.cppblog.com/Daywei0123/archive/2014/06/13/207272.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Fri, 13 Jun 2014 07:00:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/06/13/207272.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/207272.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/06/13/207272.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/207272.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/207272.html</trackback:ping><description><![CDATA[<h4><span style="font-size: 18pt">1.iterator 优先于const_iterator、reverse_iterator及const_reverse_iterator<br /></span><br /><span style="font-size: 18pt">2.使用distance和advace将容器的const_iterator转换成iterator<br /></span><br /><span style="font-size: 18pt">3.正确理解由reverse_iterator的base（）成员函数所产生的iterator的用法。<br /></span><br /><span style="font-size: 18pt">4.对于逐个字符的输入请考虑使用istreambuf_iterator</span><br /></h4><img src ="http://www.cppblog.com/Daywei0123/aggbug/207272.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-06-13 15:00 <a href="http://www.cppblog.com/Daywei0123/archive/2014/06/13/207272.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective STL(3)——关联容器</title><link>http://www.cppblog.com/Daywei0123/archive/2014/05/16/206995.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Fri, 16 May 2014 08:30:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/05/16/206995.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/206995.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/05/16/206995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/206995.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/206995.html</trackback:ping><description><![CDATA[<div><span style="font-size: 18pt">1.理解相等（equality）和等价（equivalence）的区别<br /></span><br /><span style="font-size: 14pt">相等的概念是基于operator==的。等价关系是以&#8220;在已排序的区间中对象值得相对顺序&#8221;为基础的。如果从每个标准关联容器的排列顺序来考虑等价关系，那么着将是有意义的。标准关联容器室基于等价而不是相等的。</span><span style="font-size: 14pt">标准关联容器总是保持排列顺序的，所以每个容器必须有一个比较函数（默认less）来决定保持怎样的顺序。等价是按照</span><u style="font-size: 14pt"><strong>比较函数子。</strong></u><span style="font-size: 14pt">因此，标准关联容器的使用者要为所使用的每个容器指定一个比较函数（用来决定如何排序）。如果该关联容器使用相等来决定两个对象是否有相同的值，那么每个关联容器除了用于排序的比较函数外，还需要另一个比较函数来决定两个值是否相等（默认情况下，该比较函数应该是equal_to，但有趣的是equal_to从来没有被用做STL的默认比较函数。当STL中需要相等判断时，一般的惯例是直接调用operator==。比如，非成员函数find算法就是这么做的）<br /></span><br /><span style="font-size: 18pt">2.为包含指针的关联容器指定比较类型<br /></span><br /><span style="font-size: 14pt">why？第一条已经说明关联容器是要排序。每当你要创建包含指针的关联容器时，一定要记住，容器将会按照指针的值进行排序。一般是不是你希望的，所以你几乎要创建自己的函数子类作为该容器的比较类型。<br /></span><br /><span style="font-size: 18pt">3.总是让比较函数在等值情况下返回false<br /></span><br /><span style="font-size: 14pt">比较函数的返回值表明的是按照该函数定义的排列顺序，一个值是否在另一个之前。相等的值从来不会有前后顺序关系，所以，对于相等的值，比较函数应该始终返回false。<br /></span><br /><span style="font-size: 18pt">4.切勿直接修改set或multiset中的键。<br /></span><br /><span style="font-size: 18pt">5。考虑用排序的vector替代关联容器<br /><br /></span><span style="font-size: 14pt">在排序的vector中存储数据可能比在标准关联容器中存储同样的数据要耗费更少的内存，而考虑到页面错误的因素，通过二分搜索法来查找一个排序的vector可能比查找一个标准关联容器要更快一些。</span><span style="font-size: 18pt"><br /></span><br /><span style="font-size: 18pt">6.当效率至关重要时，请在map::operator[]与map::insert之间谨慎做出选择<br /></span><br /><span style="font-size: 14pt">map::operator[]的设计目的是为了提供&#8220;添加和更新&#8221;的功能。添加一个新元素最好选后者insert。<br /></span><br /><span style="font-size: 18pt">7.熟悉非标准的散列容器。</span></div><img src ="http://www.cppblog.com/Daywei0123/aggbug/206995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-05-16 16:30 <a href="http://www.cppblog.com/Daywei0123/archive/2014/05/16/206995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective STL (2)——vector 和 string</title><link>http://www.cppblog.com/Daywei0123/archive/2014/04/20/206655.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Sun, 20 Apr 2014 06:10:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/04/20/206655.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/206655.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/04/20/206655.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/206655.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/206655.html</trackback:ping><description><![CDATA[<div><span style="font-size: 18pt">1.vector和string优先于动态分配的数组。<br /></span><br /><span style="font-size: 18pt">2.使用reserve来避免不必要的重新分配</span><br />&nbsp;&nbsp;&nbsp;<span style="font-size: 12pt"> 关于stl容器会自动增长以便容纳下你放入其中的数据，只要没有超过它们的最大限制就可以。对于vector和string，增长过程是这样实现的：每当需要更多空间时，就调用与realloc类似的操作。这一类似于relloc的操作分为如下4部分：</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （1）分配一块大小为当前容量的某个倍数的新内存。在大多数实现中，vector和string的容量每次以2的倍数增长，即每当容器需要扩张时，它们的容量即加倍。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （2）把容器的所有元素从旧的内存复制到新的内存中。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （3）析构掉旧内存中的元素</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（4）释放旧内存</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp; reserve成员函数能使你把重新分配的次数减少到最低限度，从而避免了重新分配和指针迭代器引用失效带来的开销。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp; 简单概括一下四个相互关联、但有时会被混淆的成员函数。在标准容器中，只有vector和string提供了所有这四个函数：</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （1）size（） 告诉你容器中有多少个元素，它不会告诉你该容器为自己所包含的元素分配了多少内存。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （2）capacity（）告诉你容器利用已经分配的内存可以容纳多少元素。这是容器所能容纳的元素总数，而不是它还能容纳多少个元素。如果你想知道一个vector有多少未被使用的内存，就得从capacity（）中减去size（）。如果size和capacity返回同样的值，就说明容器中不再有剩余空间了，因此下一个插入操作（push_back）将导致上面所提到的重新分配过程。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （3）resize（xx）强迫容器改变到包含n个元素的状态。在调用resize之后，size将返回n。如果n比当前的大小（size）要小，则容器尾部的元素将会被析构掉。如果n比当前的大小要大，则通过默认构造函数创建的新元素将被添加到容器的末尾。如果n比当前的容量要大，那么在添加元素之前，将先重新分配内存。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （4）reserve（xx）强迫容器把它的容量变为至少是n，前提是n不小于当前的大小。这通常会导致重新分配，因为容量需要增加。（如果n比当前的容量小，则vector什么也不做）</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因此，避免重新分配的关键在于，尽早的只用reserve，把容器的容量设为足够大的值，最好是在容器刚被构造出来之后就使用reserve。</span><br /><br /><span style="font-size: 18pt">3.注意string实现的多样性</span><br />&nbsp;&nbsp;&nbsp; <br /><span style="font-size: 18pt">4.了解如何把vector和string数据传给旧的API</span><br /><br /><span style="font-size: 18pt">5.使用&#8220;swap技巧&#8221;除去多余的容量。</span><br /><br /><span style="font-size: 18pt">6.避免使用vector&lt;bool&gt;</span><br />&nbsp;&nbsp;&nbsp;<span style="font-size: 12pt"> vector&lt;bool&gt;不是一个stl容器，也不存储bool。在一个典型的实现中，储存在vector中的每个bool仅占一个二进制位，一个8位的字节可容纳8g个&#8220;bool&#8221;。在内部vector&lt;bool&gt;使用了与位域一样的思想，来表示它所存储的那些bool；实际上只是假装存储了这些bool。</span><br /><span style="font-size: 12pt">&nbsp;&nbsp;&nbsp;&nbsp; vector&lt;bool&gt;不完全满足STL容器的要求；你最好不要使用它；你可以使用deque&lt;bool&gt;和bitset来替代它，这两个数据结构几乎能做vector&lt;bool&gt;所能做的一切事情。</span></div><img src ="http://www.cppblog.com/Daywei0123/aggbug/206655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-04-20 14:10 <a href="http://www.cppblog.com/Daywei0123/archive/2014/04/20/206655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective STL （1）</title><link>http://www.cppblog.com/Daywei0123/archive/2014/04/04/206473.html</link><dc:creator>Daywei</dc:creator><author>Daywei</author><pubDate>Fri, 04 Apr 2014 13:10:00 GMT</pubDate><guid>http://www.cppblog.com/Daywei0123/archive/2014/04/04/206473.html</guid><wfw:comment>http://www.cppblog.com/Daywei0123/comments/206473.html</wfw:comment><comments>http://www.cppblog.com/Daywei0123/archive/2014/04/04/206473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Daywei0123/comments/commentRss/206473.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Daywei0123/services/trackbacks/206473.html</trackback:ping><description><![CDATA[<p><span style="font-size: 14pt"><strong>&nbsp;慎重选择容器类型 </strong></span><br />&nbsp;标准序列容器：vector string deque list<br />&nbsp;标准关联容器 : set multiset map multimap<br />&nbsp;非标准序列容器: slist rope. slist 是一个单向链表，rope 本质上市一个&#8220;重型&#8221;string<br />&nbsp;非标准的关联容器 hash_set hash_nultiset hash_map hash_multimap vector<char> 作为string的替代。 vector 作为标准关联容器的替代 <br />&nbsp;几种标准的非STL容器 包括 数组、bitset valarray stack queue 和 priority_queue<br /><br /><strong><u>&nbsp;容器可分类为 连续内存容器和基于节点的容器<br /></u></strong><br />连续内存容器把它的元素存放在一块或多块（动态分配的）内存中，每块内存中存有多个元素。当有新元素插入或已有的元素被删除时，同一内存块中的其他元素要向前或向后移动，以便为新元素让出空间，或者填充被删除元素所留下的空隙。 <br />基于节点的容器在每一个（动态分配的）内存块中只存放一个元素。容器中元素的插入或删除只影响到指向节点的指针，而不影响节点本身的内容，所以当有插入或删除操作时，元素的值不需要移动。<br /><br />你是否需要在容器的任意位置插入新元素？如果需要，就选择序列容器；关联容器是不行的。<br />你是否关心容器中的元素师排序的？如果不关心，则哈希容器室一个可行的选择方案；否则，你要避免哈希容器。<br />容器中数据的布局是否需要和C兼容？如果需要兼容，就只能选择vector。<br />元素的查找速度是否是关键的考虑因素？如果是，就要考虑哈希容器、排序的vector和标准关联容器&#8212;&#8212;或许这就是优先顺序。<br /><br /><br /><span style="font-size: 14pt"><strong>确保容器中的对象拷贝正确而高效<br /><br />调用empty而不是检查size（）是否为 0<br /></strong></span><span style="font-size: 12pt">理由很简单：empty对所有的标准容器都是常数时间操作，而对一些list实现，size耗费线性时间。由于list所独有的链接操作。<br /><br /></span><span style="font-size: 14pt"><strong>区间成员函数优先于与之对应的单元素成员函数。<br /><br /></strong></span><span style="font-size: 14pt"><strong>如果容器中包含了通过new操作创建的指针，切记在容器对象析构前将指针delete掉。切勿创建包含auto_ptr的容器对象。问题的根源只是在于auto_ptr不是这样的智能指针。</strong></span><span style="font-size: 12pt"><br />永远都不要错误的认为：你可以通过创建auto_ptr的容器使指针被自动删除。<br /><br /><font size="5"><strong>慎重选择删除元素的方法<br /></strong>erase是指向紧随被删除元素的下一个元素的有效迭代器。</font><span style="font-size: 12pt"><br /><br /></span><strong><u><em>要删除容器中有特定值得所有对象</em></u></strong><br />&nbsp; 如果容器使vector、string或deque，则使用earse-remove习惯用法。 <br />&nbsp; 如果容器是list，则使用list::remove<br />&nbsp; 如果容器是一个标准关联容器，则使用它的erase成员函数。<br /><br /><strong><em><u>要删除容器中满足特定判别式（条件）的所有对象</u></em></strong><br />&nbsp; 如果容器是vector、string或deque，则使用erase-remove_if的习惯用法。<br />&nbsp; 如果容器是list，则使用list::remove_if。<br />&nbsp; 如果容器使一个标准关联容器，则使用remove_copy_if和swap，或者写一个循环来遍历容器中的元素，记住当把迭代器传给erase时，要对它进行后缀递增。<br /><br /><strong><em><u>要在循环内部做某些（除了删除对象之外的）操作</u></em></strong><br />&nbsp; 如果容器使一个标准序列容器，则写一个循环来遍历容器中的元素，记住每次调用erase时，要用它的返回值更新迭代器。<br />&nbsp; 如果容器是一个标准关联容器，则写一个循环来遍历容器中的元素，记住当把迭代器传给erase时，要对迭代器作后缀递</span><span style="font-size: 14pt">增。<br /><br /></span><span style="font-size: 14pt"><strong>切勿对STL容器的线程安全性有不切实际的依</strong><span style="font-size: 14pt"><strong>赖。<br /></strong></span><br /></span><span style="font-size: 12pt">&nbsp; 你不能指望STL库会把你从手工同步控制中解脱出来，而且你不能依赖于任何线程的支持。</span><span style="font-size: 14pt"><br /></span><span style="font-size: 12pt">&nbsp; 在容器所返回的每个迭代器的生存期结束前，都锁住容器<br /></span><span style="font-size: 12pt">&nbsp; 对于作用于容器的每个算法，都锁住该容器，直到算法结束。</span><span style="font-size: 12pt">&nbsp; 多个线程读是安全的<br /></span><span style="font-size: 12pt">&nbsp; 多个线程对不同的容器作写入操作时安全的。<br /></span><span style="font-size: 12pt">&nbsp; 对容器成员函数的每次调用，都锁住容器直到调用结束。</span></p> <img src ="http://www.cppblog.com/Daywei0123/aggbug/206473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Daywei0123/" target="_blank">Daywei</a> 2014-04-04 21:10 <a href="http://www.cppblog.com/Daywei0123/archive/2014/04/04/206473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>