• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            2016年9月11日

            CMake使用

            cmake學(xué)習(xí)(一)靜態(tài)庫與動態(tài)庫構(gòu)建

            (.so)共享庫,shared object:節(jié)省空間,在運(yùn)行時(shí)去連接,如果執(zhí)行機(jī)器上沒有這些庫文件就不能執(zhí)行。
            (.a)靜態(tài)庫,archive:靜態(tài)庫和程序化為一體,不會分開。
            通過 ldd命令可以查看一個可執(zhí)行程序所依賴的的共享庫。
            使用環(huán)境變量LD_LIBRARY_DIRECTORY可以指定共享庫位置


            一、編譯共享庫:
            ADD_LIBRARY(hello SHARED ${SHARED_LIBRARY})

            二、添加靜態(tài)庫:
            ADD_LIBRARY(hello STATIC ${STATIC_LIBRARY})
            因?yàn)槟J(rèn)規(guī)則是不能有相同名字的共享庫與靜態(tài)庫,所以當(dāng)生成靜態(tài)庫的時(shí)候(so后綴),共享庫會被刪除,因?yàn)橹荒茉试S一個名字存在,相同名字的會被替代(hello),所以需要通過SET_TARGET_PROPERTIES()來解決這個問題,例子:
            SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
            cmake在構(gòu)建一個target的時(shí)候,會刪除之前生成的target,一樣是通過設(shè)置SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)來達(dá)到目的
            三、動態(tài)庫的版本號:
            同樣是通過SET_TARGET_PROPERTIES()來設(shè)置
            SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
            VERSION:動態(tài)庫版本
            SOVERSION:API版本
            最后生成的結(jié)果是:
            libhello.so.1.2
            libhello.so.1->libhello.so.1.2
            libhello.so->libhello.so.1
            四、安裝:
            INSTALL(TARGETS hello hello_static
            LIBRARY DESTINATION lib
            ARCHIVE DESTINATION lib)
            INSTALL(TARGETS hello.h
            DESTINATION include/hello)
            其他常用的屬性 PERMISSIONS:設(shè)置權(quán)限;RATTERN:設(shè)置正則表達(dá)式


            Summary:
            ADD_LIBRARY():添加一個庫,共享庫,靜態(tài)庫,模塊
            SET_TARGET_PROPERTIES():設(shè)置輸出名稱,版本號,解決相同target被刪除的問題
            GET_TARGET_PROEERTIES():與SET功能相對

            cmake學(xué)習(xí)(二)常用變量和常用環(huán)境變量
            一、變量的引用方式是使用“${}”,在IF中,不需要使用這種方式,直接使用變量名即可
            二、自定義變量使用SET(OBJ_NAME xxxx),使用時(shí)${OBJ_NAME}
            三、cmake的常用變量:
            CMAKE_BINARY_DIR,PROJECT_BINARY_DIR,_BINARY_DIR:
            這三個變量內(nèi)容一致,如果是內(nèi)部編譯,就指的是工程的頂級目錄,如果是外部編譯,指的就是工程編譯發(fā)生的目錄。
            CMAKE_SOURCE_DIR,PROJECT_SOURCE_DIR,_SOURCE_DIR:
            這三個變量內(nèi)容一致,都指的是工程的頂級目錄。
            CMAKE_CURRENT_BINARY_DIR:外部編譯時(shí),指的是target目錄,內(nèi)部編譯時(shí),指的是頂級目錄
            CMAKE_CURRENT_SOURCE_DIR:CMakeList.txt所在的目錄
            CMAKE_CURRENT_LIST_DIR:CMakeList.txt的完整路徑
            CMAKE_CURRENT_LIST_LINE:當(dāng)前所在的行
            CMAKE_MODULE_PATH:如果工程復(fù)雜,可能需要編寫一些cmake模塊,這里通過SET指定這個變量
            LIBRARY_OUTPUT_DIR,BINARY_OUTPUT_DIR:庫和可執(zhí)行的最終存放目錄
            PROJECT_NAME:你猜~~

             

            四、cmake中調(diào)用環(huán)境變量
            1.Using $ENV{NAME} : invoke system environment varible.
            We can use "SET(ENV{NAME} value)" as well. note that the "ENV" without "$".
            2.CMAKE_INCLUDE_CURRENT_DIR equal to INCLUDE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})


            五、其他的內(nèi)置變量
            1.BUILD_SHARED_LIBS:set the default value when using ADD_LIBRARY()
            2.CMAKE_C_FLAGS: set compiler for c language
            2.CMAKE_CXX_FLAGS: set compiler for c++ language


            六、區(qū)分debug和release
            在工程目錄下,cmake -DCMAKE__BUILD_TYPE=DEBUG(RELEASE),再執(zhí)行make


            七、指定編譯32bit或64bit程序
            SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
            SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")

            cmake學(xué)習(xí)(三)常用指令

            一、基本指令:
            INCLUDE_DIRECTORIES(${includedir}) #-I。
            LINK_DIRECTORIES(${libdir}) #-L
            TARGET_LINK_LIBRARIES(helloworld ${linkflags}) #-l
            ADD_DEFINITIONS(${cflags}) #-D
             
            1、ADD_DEFINATIONS:向C/CPP添加宏定義,相當(dāng)于gcc中的-D,參數(shù)之間用空格分割
            2、ADD_DEPENDICIES(target_name, depend_name):定義target對其他target的依賴關(guān)系
            3、AUX_SOURCE_DIRECTORY(dir VARIBLE):把目錄下的所有源文件保存在變量中,基本用來創(chuàng)建源文件列表
            4、ADD_EXECUTABLE:指定目錄,生成執(zhí)行文件
            5、EXEC_PROGRAM:外部調(diào)用指令,可移執(zhí)行任何外部命令,后面加參數(shù),例子如下:
            EXEC_PROGERAM(ls ARGS"*.c" OUTPUT_VARIBLE LS_OUTPUT RETURN_VALUE LS_RVALUE)
            IF(not LS_RVALUE)
            MESSAGE(STATUS "xxx")
            ENDIF(not LS_RVAULE)
            PS.這里執(zhí)行l(wèi)s *.c指令,執(zhí)行成功的話,返回0。
            6、FILE指令:
            FILE(WRITE file_name "content")
            FILE(APPEND file_name "content")
            FILE(READ file_name varible)
            FILE(WRITE file_name "content")
            7、FIND_系列指令:
            LIBRARY( name path):
            FIND_LIBRARY(Xorg X11 /usr/lib64)
            IF(not Xorg)
            MESSAGE(STATUS "no Xorg")
            ENDIF(not Xorg)
            FILE( name path)
            PATH( name path)
            PROGRAM( name path)
            PACKAGE( [major.minor][QUIET][NO MODULE][[REQUIRED][COMPONTS][componts....]])
            最后一條,用來調(diào)用放在CMAKE_MODULE_PATH下的Find.cmake模塊,也可以自定義Find模塊
            首先通過SET(CMAKE_MODULE_PATH /home/...)來指定位置

            8、控制指令:
            IF(expression),ELSE(expression),ENDIF(expression)
            express舉例:
            否定:空,0,N,NO,OFF,F(xiàn)ALSE,NOTFOUND或_NOTFOUND
            肯定:COMMAND cmd,EXISTS dir/file,variable MARCHES regex等等等等還有很多~~~隨用隨查吧


            cmake學(xué)習(xí)(四)模塊的使用和自定義模塊

            FIND_PACKAGE
            每一個模塊都會產(chǎn)生如下變量
            _FOUND
            _INCLUDE_DIR
            _LIBRARY or _LIBRARIES
            如果_FOUND為真,把_INCLUDE_DIR加入到INCLUDE_DIRECTORIES中,_LIBRARY加入到TARGET_LINK_LIBRARIES中。

            編寫屬于自己的FindHello模塊:
            1.FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello)
            2.FIND_LIBRARY(HELLO_LIBRARY_DIR NAMES hello PATH /usr/lib /usr/local/lib)
              IF(HELLO_INCLUDE_DIR AND HELLO_LIBRARY)
              SET(HELLO_FOUND TRUE)
              ENDIF(HELLO_INCLUDE_DIR)
            3.FIND_PACKAGE([major.minor][QUIET][NO_MODULE]
            [[REQUIRED|COMPONENTS][componets...]])
            QUIET參數(shù):去掉輸出信息
            REQUIRED參數(shù):共享庫是否是工程必須的,如果是必須的,那么找不到
            如果在src中想調(diào)用hello模塊中的內(nèi)容
            FIND_PACKAGE(HELLO)
            為了可以讓工程找到FindHELLO.cmake
            在主工程的CMakeList.txt中,SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_PATH}/cmake)
            通過設(shè)置FIND_PACKAGE(HELLO QUIET)可以去掉輸出信息

            Cmake CMAKE_BUILD_TYPE specification

            That’s because no build type has been specified to CMake. The build type is a feature most IDE have, it allows you to compile your program in “debug” mode, for easily single-stepping through it with a debugger, or in “release” mode, with speed optimization enabled.

            To fix this you simply need to specify a build type in the CMakeLists.txt file, in this way:


            if( NOT CMAKE_BUILD_TYPE )
              set( CMAKE_BUILD_TYPE Debug CACHE STRING
                   "Choose the type of build, options are: None Debug Release RelWithDebInfo
            MinSizeRel."
                   FORCE )
            endif()
            
            
            when cmake is run without specifying the build type using -D CMAKE_BUILD_TYPE, it is the Debug mode that is selected as the default.


             

            posted @ 2016-09-11 22:52 Daywei 閱讀(1264) | 評論 (0)編輯 收藏

            2016年6月28日

            SDL認(rèn)識

                 SDL是一個輕量級的,用C語言開發(fā)的多媒體庫。它包含了圖像繪制、文字繪制、事件處理、聲音播放等模塊。因?yàn)镾DL的易用以及它的擴(kuò)展庫的完整性,很多2D游戲都使用SDL開發(fā),其中就包括這幾年大熱的移動平臺上的游戲《憤怒的小鳥》。

            然后說說從個人角度上看SDL的特點(diǎn)。

            1.跨平臺。確確實(shí)實(shí)是跨了N個平臺,甚至包括NDS這種平臺。有了SDL,你甚至可以在windows、linux、Android上任意移植你的游戲。當(dāng)然,前提是你目標(biāo)平臺的編譯器認(rèn)識你的代碼( ̄▽ ̄)”。有了SDL泥甚至可以只用c語言開發(fā)安卓游戲喲。

            2.開源。

            3.SDL2.0繪圖效率很高。事實(shí)上相較之SDL1.2我個人比較喜歡SDL2.0的原因也是在此。個人感覺(其實(shí)我沒看過源碼)SDL1.2應(yīng)該是個跟當(dāng)年的DirectDraw差不多的東西,像素填充什么的,有相當(dāng)程度上是要磨CPU的。而SDL2.0從繪圖方式上就革新了,拋棄了之前的surface與clip的模式,把實(shí)際繪制的東西改為了Texture,而把之前的surface改為了創(chuàng)建Texture的一個臨時(shí)環(huán)節(jié)。而texure,顧名思義,其實(shí)就是DirectX、OpenGL這些底層的3D硬件加速API的貼圖。

            當(dāng)下DirectX、OpenGL標(biāo)準(zhǔn)下的顯卡的渲染管線無非就是:1.把頂點(diǎn)(可以理解成坐標(biāo))傳給顯卡 。2.把texture傳給顯卡。 3.告訴顯卡怎么處理這些數(shù)據(jù)(shader)。 4.顯卡把東西給你顯示出來。而基于DirectX、OpenGL(移動平臺是OpenGL ES)的SDL2.0,正是恰好地利用了當(dāng)下顯卡的能力。

            4.SDL可以用作3D圖像引擎和底層DirectX/OpenGL API的中間層。當(dāng)然,其實(shí)如果把SDL這樣用的話,那就真是很薄的一層了:)

            5.易用。這是相對而言的,比如在windows上,你用了SDL這個庫之后,基本就不用去理會Windows那些又臭又長用不著的參數(shù)又多的API了。我不是在討論信仰問題也不是要詆毀windows,我是在客觀陳述windows api那個要初始化一個窗口必須要堆100行代碼的設(shè)定實(shí)在是打擊初學(xué)者積極性的事實(shí)。

            SDL_image、SDL_ttf、SDL_mixer、SDL_net 外部擴(kuò)展庫,也是不錯的選擇。

            性能沒有測試,僅從寫代碼角度上來說,個人感覺2.0將操作給弄得復(fù)雜了。

            1.2---------------------------------------
            只有SDL_Surface的概念,屏幕是surface,圖片,文字等都是surface,
            只要將準(zhǔn)備好的各種圖片,貼到屏幕里去(SDL_BlitSurface);再刷一下屏幕(SDL_Flip全局的、或SDL_UpdateRect局部的)就ok了。。。

            SDL_Init(SDL_INIT_EVERYTHING);

            SDL_Surface* screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
            SDL_Surface* bmp = SDL_LoadBMP("back.bmp");
            SDL_BlitSurface(bmp, 0, screen, 0);
            SDL_Flip(screen);

            while(SDL_WaitEvent(&e)) {
            switch(e.type) {
            case SDL_QUIT:
            return;
            }
            }
            SDL_Quit();
            2.0---------------------------------------
            整出了SDL_Window,SDL_Renderer,SDL_Texture新的3個東西。
            并且我要畫一張圖,先要得到surface,然后轉(zhuǎn)換為texture,再臨時(shí)貼到renderer,最后才刷屏。

            SDL_Init(SDL_INIT_EVERYTHING);

            SDL_Window* window = SDL_CreateWindow("hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
            SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            SDL_Surface* surface = SDL_LoadBMP("back.bmp");
            SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, 0, 0);
            SDL_RenderPresent(renderer);

            while(SDL_WaitEvent(&e)) {
            switch(e.type) {
            case SDL_QUIT:
            return;
            }
            }
            SDL_Quit();

            其實(shí),我真心不覺得提出SDL_Window,SDL_Renderer,SDL_Texture這些概念先進(jìn)性在哪里?可能是與openGL的概念保持一致吧。
            而且從維護(hù)的角度出發(fā),不管sdl2.0性能提升了多少,如果接口本身不需要改動,不是更加好么?

            ---------------------------------------------
            最后我發(fā)現(xiàn),同樣是渲染的窗口
            1.2用SDL_Flip(screen);之后被其他窗口擋住之后,回來畫面還是在的;
            2.0用SDL_RenderPresent(renderer);之后被其他窗口擋住之后,回來畫面就不在了;

            posted @ 2016-06-28 00:17 Daywei 閱讀(674) | 評論 (0)編輯 收藏

            2015年12月6日

            OpenCV 使用問題記錄

                 摘要:     OpenCV從1.0到現(xiàn)在的3.0,變化還是相當(dāng)大的。大趨勢是從C結(jié)構(gòu)層次到C++類層次的轉(zhuǎn)變。先從OpenCV底層的圖像數(shù)據(jù)結(jié)構(gòu)談起,1.0時(shí) 圖像數(shù)據(jù)結(jié)構(gòu)是IplImage,之后是cvmat,之后2.2中出現(xiàn)了CvvImage,之后就是cv::mat,2.3之后CvvImage就被廢棄了。 opencv中對圖像的處理是最基本的操作,一般的圖像類型為Ipl...  閱讀全文

            posted @ 2015-12-06 12:20 Daywei 閱讀(1953) | 評論 (0)編輯 收藏

            2015年3月17日

            SQL使用記錄

                 摘要: 問題:Update字段來自子查詢或者來自其他表字段 Update 語句 Update 語句用于修改表中的數(shù)據(jù)。 語法:UPDATE 表名稱 SET 列名稱 = 新值 WHERE 列名稱 = 某值SQL update select語句 最常用的update語法是: UPDATE <table_name> SET <column_name1> = <value&...  閱讀全文

            posted @ 2015-03-17 15:43 Daywei 閱讀(761) | 評論 (0)編輯 收藏

            2014年8月22日

            Exceptional C++ 讀書筆記2

            永遠(yuǎn)不要用#include包含不必要的頭文件

            如果只需要流的前置聲明,應(yīng)該優(yōu)先使用#include<iosfwd>

            只需要前置聲明時(shí),絕不要用#include包含相應(yīng)的頭文件。

            如果使用聚合關(guān)系就已經(jīng)足夠,就不要使用繼承。

            要避免使用內(nèi)聯(lián)或者復(fù)雜的調(diào)整方法,除非通過性能分析證明這確實(shí)是必要的。

            正確使用名字空間。如果將一個類放入名字空間,那么同時(shí)要保證將這個類的所有輔助函數(shù)和運(yùn)算符函數(shù)也放入相同的名字空間。否則,你將在代碼中發(fā)現(xiàn)奇怪的結(jié)果。
            要理解這五種不同類型的內(nèi)存,了解他們?yōu)槭裁词遣煌模约八麄兏髯缘男袨橛质窃趺礃樱簵#ㄗ詣幼兞浚⒆杂纱鎯Γ╪ew/delete)、堆(malloc/free)、全局(靜態(tài)變量、全局變量、文件作用域變量等)、常量數(shù)據(jù)(字符串常量等)。

            優(yōu)先使用自由存儲(new/delete),避免使用堆(malloc/free)。

            對于“堆”和“自由存儲”進(jìn)行區(qū)分,這一點(diǎn)很重要,因?yàn)樵贑++標(biāo)準(zhǔn)中有意避開了這兩種類型的內(nèi)存是不是相關(guān)的這個問題。例如,當(dāng)通過::operator delete()函數(shù)來釋放內(nèi)存時(shí),在C++標(biāo)準(zhǔn)的18.4.1.1中,最后一項(xiàng)是這樣的:
            “ 在C++標(biāo)準(zhǔn)中并沒有規(guī)定,在哪些情況下,在通過operator delete回收的存儲空間中,有一部分或者全部的控件可以再隨后調(diào)用operator new或者calloc,malloc以及realloc等函數(shù)時(shí)被重新分配,這些函數(shù)的聲明時(shí)在<cstdlib>中。”
            而且,在C++標(biāo)準(zhǔn)中也沒有規(guī)定,new/delete是否需要通過malloc/free來實(shí)現(xiàn)。不過,在C++標(biāo)準(zhǔn)20.4.6節(jié)的第3段和第4段中規(guī)定了,malloc/free一定不能使用new/delete來實(shí)現(xiàn):“calloc、malloc和realloc函數(shù)不會通過調(diào)用::operator new()來分配存儲空間。函數(shù)free()不會通過調(diào)用::operator delete() 來釋放內(nèi)存。”

            如果在類中定義了new和delete中的任意一個運(yùn)算符函數(shù),那么一定要同時(shí)定義另外一個。

            通常應(yīng)該顯式地將函數(shù)operator new ()和operator delete()聲明為靜態(tài)函數(shù)。他們永遠(yuǎn)都不能使非靜態(tài)成員函數(shù)。

            永遠(yuǎn)都不要通過多態(tài)的方式處理數(shù)組。

            優(yōu)先選擇使用vector或者deque,而不是數(shù)組。

            在編寫拷貝賦值運(yùn)算符函數(shù)時(shí),永遠(yuǎn)都不要指望能夠通過對自我賦值進(jìn)行檢測來保證函數(shù)的正確性;應(yīng)該在拷貝賦值運(yùn)算符函數(shù)中使用“創(chuàng)建臨時(shí)對象并進(jìn)行交換”的慣用法,這種方法不僅是異常安全的,而且在處理自我賦值時(shí)也是安全的。

            可以將自我賦值檢測作為一種優(yōu)化手段,以避免不必要的工作,這是正確地做法。

            不僅要避免編寫類型轉(zhuǎn)換運(yùn)算符函數(shù),而且還要避免編寫隱式的構(gòu)造函數(shù)。

            盡量編寫異常安全的代碼。在編寫代碼時(shí)應(yīng)該始終遵循:即使在出現(xiàn)異常時(shí),資源仍然能夠被正確地釋放,并且數(shù)據(jù)也總是處于一致的狀態(tài)。

            避免使用語言中那些不常用的特性,而應(yīng)該使用最簡單并且有效的技術(shù)。

            拷貝初始化過程絕不是賦值過程,因此在初始化中永遠(yuǎn)都不會調(diào)用函數(shù)T::operator=()。是的,我知道在初始化語句中有一個“=”符合,但不要被它迷惑。它只是從C語言中沿用過來的一種語法,并不代表賦值運(yùn)算。

            如果可能的話,優(yōu)先使用“T t(u);”這種形式,而不是“T t=u;”的形式。通常,能能夠時(shí)候后者的地方,都可以使用前者,并且使用前者還有更多的好處——例如,可以帶多個參數(shù)。

            在函數(shù)聲明中,如果參數(shù)是以傳值方式來傳遞的,則不要使用const。而如果在這個函數(shù)的定義中,參數(shù)是不能被修改的,那么應(yīng)該使用const。

            對于不是內(nèi)置類型的返回值來說,當(dāng)使用返回值的方式而不是返回引用的方式時(shí),應(yīng)該優(yōu)先選擇返回const值。

            const 和mutable都是你的朋友

            優(yōu)先使用新形式的類型轉(zhuǎn)換。

            不要通過類型轉(zhuǎn)換去掉常量屬性,而應(yīng)該使用mutable。

            避免使用向下的類型轉(zhuǎn)換。

            優(yōu)先通過引用方式來傳遞對象參數(shù),而不是傳值方式,并且在所有可能的地方都使用const。

            避免使用內(nèi)聯(lián),除非從性能的分析上來看確實(shí)有必要這么做。

            避免使用全局變量或者靜態(tài)變量。如果必須使用,那么一定要特別注意這些變量的初始化順序。

            在構(gòu)造函數(shù)的初始化列表中,應(yīng)該把 基類按照他們在類定義中出現(xiàn)的先后順序進(jìn)行排列。

            在編寫代碼時(shí),永遠(yuǎn)都不應(yīng)該依賴函數(shù)參數(shù)的求值順序

            posted @ 2014-08-22 15:00 Daywei 閱讀(1543) | 評論 (0)編輯 收藏

            Exceptional C++ 讀書筆記1

            絕對不要對無效的迭代器執(zhí)行解引用(dereference)操作

            用于不要將異常安全性放在事后考慮。異常安全性會影響到類的設(shè)計(jì)。它永遠(yuǎn)都不會“只是一個實(shí)現(xiàn)細(xì)節(jié)”。

            在傳遞對象參數(shù)時(shí),選擇const&方式而不是傳值方式。

            對于程序運(yùn)行中不會改變的值,應(yīng)該預(yù)先計(jì)算并保存起來備用,而不是重復(fù)地創(chuàng)建對象,這是沒有必要的。

            通常,為了保持一致性,應(yīng)該使用前置遞增來實(shí)現(xiàn)后置遞增,否則,當(dāng)其他用戶在使用你的類時(shí),可能會得到奇怪結(jié)果。

            優(yōu)先選擇使用前置遞增。只有在需要初始值時(shí),才使用后置遞增。

            在進(jìn)行隱式類型轉(zhuǎn)換時(shí),要注意在轉(zhuǎn)換過程中創(chuàng)建的 臨時(shí)對象。要避免這個問題,一個好辦法就是盡可能地通過顯式的方式來構(gòu)造對象,并避免編寫類型轉(zhuǎn)換運(yùn)算符。

            記住對象的生存期。永遠(yuǎn),永遠(yuǎn),永遠(yuǎn)都不要返回指向局部對象的指針或引用;它們沒有任何用處,因?yàn)橹髡{(diào)代碼無法跟蹤它們的有效性,但卻可能會試圖這么做。

            盡可能地重用代碼——尤其是標(biāo)準(zhǔn)庫中的代碼——而不是自己去編寫代碼,這樣更快、更容易,也更安全。

            如果在函數(shù)中不打算處理所拋出的異常,那么應(yīng)該將異常轉(zhuǎn)發(fā)給能夠進(jìn)行處理的上層調(diào)用者。

            在編寫代碼時(shí)應(yīng)該始終遵循:即使在出現(xiàn)異常時(shí),資源仍然能夠被正確地釋放,并且數(shù)據(jù)也總是處于一致的狀態(tài)。

            遵循標(biāo)準(zhǔn)的異常安全規(guī)則:永遠(yuǎn)不要在析構(gòu)函數(shù)、重載運(yùn)算符函數(shù)operator delete()或者operator delete[]()中拋出異常; 在編寫每個析構(gòu)函數(shù)和內(nèi)存釋放函數(shù)時(shí),要假設(shè)存在著“throw()”這樣的異常規(guī)范。

            遵循標(biāo)準(zhǔn)的異常安全性規(guī)則:在每個函數(shù)中,要將所有可能會拋出異常的代碼單獨(dú)放在一起,并且對這些代碼進(jìn)行安全處理。然后,當(dāng)你確認(rèn)這些代碼執(zhí)行的工作都已經(jīng)成功地完成時(shí),才可以使用不會拋出異常的操作來修改程序的狀態(tài)。

            永遠(yuǎn)都不要到最后才實(shí)現(xiàn)異常安全性。異常安全性會對類的設(shè)計(jì)產(chǎn)生影響。它永遠(yuǎn)都不會“只是一個實(shí)現(xiàn)細(xì)節(jié)”。

            優(yōu)先考慮實(shí)現(xiàn)內(nèi)聚。要努力使每段代碼——每個模塊、每個類、每個函數(shù)——都只有單一的,并且是明確定義的功能。

            “異常不安全”總是與“拙劣的設(shè)計(jì)”結(jié)伴的。如果程序的設(shè)計(jì)邏輯清晰,那么即使有一段代碼不是異常安全的,一般來說也不會有太大問題,并且可以很簡單地進(jìn)行修正。但如果有一段代碼由于設(shè)計(jì)問題而不能被編寫成異常安全的,我們通常都會認(rèn)為這個設(shè)計(jì)時(shí)拙劣的。下面是兩個拙劣設(shè)計(jì)的示例。
            示例1:如果在一個函數(shù)中需要實(shí)現(xiàn)兩個不同的功能,那么這個函數(shù)很難被編寫成異常安全的。
            示例2:如果在拷貝賦值運(yùn)算符函數(shù)中必須對自我賦值進(jìn)行檢測,那么這個函數(shù)也可能不是完全異常安全的

            遵循標(biāo)準(zhǔn)的異常安全性規(guī)則:以“獲得資源也就意味著初始化”這種模式來分離資源的所有權(quán)和資源的管理權(quán)。

            在進(jìn)行設(shè)計(jì)中,要始終牢記重用性。

            優(yōu)先采用“ a op=b;”這種寫法,而不是"a = a op b;"(這里的op表示某個運(yùn)算符)。這種寫法更為清晰,效率也高。

            如果定義了某個運(yùn)算符(例如,operator+),那么通常還應(yīng)該同時(shí)定義與這個運(yùn)算符相對應(yīng)的賦值運(yùn)算符(例如,operator+=)。并且用后者來實(shí)現(xiàn)前者。而且,還應(yīng)該維護(hù)op和op=之間的自然關(guān)系。

            在C++標(biāo)準(zhǔn)中規(guī)定:運(yùn)算符=,(),[]和->必須被定義為成員函數(shù),而在類中定義的new,new [],delete和delete[]等運(yùn)算符函數(shù)必須是靜態(tài)成員函數(shù)。對于其他的運(yùn)算符函數(shù):
                 如果運(yùn)算符函數(shù)是用于流I/O的opeator>>或者operator<<,或者如果運(yùn)算符函數(shù)需要對其左操作數(shù)進(jìn)行類型轉(zhuǎn)換,或者運(yùn)算符函數(shù)可以通過類的公有接口來實(shí)現(xiàn),那么將這個函數(shù)定義為非成員函數(shù)(在前兩種情況中,如果需要的話也可以被定義為友元函數(shù));如果運(yùn)算符函數(shù)需要實(shí)現(xiàn)虛函數(shù)的行為,那么增加一個虛函數(shù)來提供虛函數(shù)的行為,并用這個虛成員函數(shù)來實(shí)現(xiàn)運(yùn)算符函數(shù)否則將預(yù)算富函數(shù)定義為成員函數(shù)。

            在函數(shù)opeator>>和operator<<中應(yīng)該始終返回對流對象的引用。

            將基類的析構(gòu)函數(shù)定義為虛函數(shù)(除非你能保證,永遠(yuǎn)都不會有人通過指向基類的指針來刪除派生類的對象)。

            如果在派生類中定義的函數(shù)與基類中的函數(shù)有相同的名字,并且你不想隱藏基類中函數(shù),那么應(yīng)通過using聲明語句將基類的這個函數(shù)引入到派生類的作用域中。

            永遠(yuǎn)不要改變被覆蓋的基類函數(shù)中的默認(rèn)參數(shù)值。

            除了對真正的Liskov IS-A和WORKS-LIKE-A關(guān)系進(jìn)行建模之外,永遠(yuǎn)都不要使用共有繼承。所有被覆蓋的成員函數(shù)不能超過實(shí)際需求的范圍,同時(shí)也不能小于這個范圍。

            使用公有繼承的目的是重用代碼(編寫以多態(tài)的方式使用基類對象的代碼),而重用(基類中的)代碼并不一定要使用公有繼承。

            對“is implemented in terms of”這種關(guān)系建模時(shí),應(yīng)該優(yōu)先選擇成員關(guān)系/包含的方式,而不是私有繼承的方式。只有非用繼承不可時(shí),才應(yīng)該使用私有繼承——也就是說,當(dāng)需要訪問保護(hù)成員或者需要覆蓋虛函數(shù)時(shí),才使用私有繼承。永遠(yuǎn)都不要只是為了代碼重用而使用共有繼承。

            對于廣泛使用的類,應(yīng)該優(yōu)先使用編譯器防火墻這種慣用法(也叫做Pimpl慣用法)來隱藏實(shí)現(xiàn)細(xì)節(jié),通過一個不透明的指針(指向一個進(jìn)行了前置聲明但又沒有定義的類)來保存私有成員(包括狀態(tài)變量和成員函數(shù)),聲明這個指針時(shí)可采用“struct XxxxImpl* pImpl;XxxxImpl* pimpl_;”這樣的形式。例如:“class map{ private :struct MapImpl;MapImpl* pimpl_;}”

            包含,也可以叫做“聚合”,“分層”,“HAS-A”或者“委托”。優(yōu)先選擇包含而不是繼承,對于IS-IMPLEMENTED-IN-TERMS-OF這種關(guān)系建模時(shí),應(yīng)該優(yōu)先考慮使用包含,而不是繼承。

            posted @ 2014-08-22 11:50 Daywei 閱讀(1600) | 評論 (0)編輯 收藏

            2014年7月24日

            從缺陷中學(xué)習(xí)C/C++


            有符號int與無符號int比較的后果
            int i = -1;
            unsigned 
            int ud=1;
            if(i < ud)
            {
                printf(
            "true");
            }

            else
            {
                printf(
            "false");
            }
            一看結(jié)果應(yīng)該是打印出true,但事實(shí)卻是false。
            signed int 型變量被轉(zhuǎn)換成unsigned int型變量。-1轉(zhuǎn)換成unsigned int的結(jié)果是一個非常巨大的正整數(shù)(32位系統(tǒng)上是2的32次方-1),需要進(jìn)行強(qiáng)轉(zhuǎn)為int型。

            位域變量
            struct data
            {
            int flag:1;
            int other:31;
            }
            ;
            printf(
            "data size %d\n",sizeof(data));
            data test1;
            test.flag
            = 1;
            if(test.flag ==1)
            {
            printf(
            "true");
            }

            else
            {
            printf(
            "false");
            }
            int的位域變量,而用一個bit表示int時(shí),這一位是用來表示有符號位的,帶符號的一個bit的位域變量的取值范圍是0或-1.無符號的一個bit的位域變量的取值范圍是0或1,故1賦給flag時(shí)會出現(xiàn)溢出,flag變?yōu)?1.
            Reference:http://wenku.baidu.com/view/670eff4bf7ec4afe04a1dfd7.html

            posted @ 2014-07-24 15:29 Daywei 閱讀(1386) | 評論 (0)編輯 收藏

            2014年6月25日

            Effective STL(5)——算法

            1.確保目標(biāo)空間足夠大

            2.了解各種與排序有關(guān)的選擇
              如果需要對vector、string、deque或者數(shù)組中的元素執(zhí)行一次完全排序,那么可以使用sort或者stable_sort。
              如果有一個vector、string、deque或者數(shù)組,并且只需要對等價(jià)性最前面的n個元素進(jìn)行排序,那么可以使用partial_sort。
              如果有一個vector、string、deque或者數(shù)組,并且需要找到第n個位置上的元素,或者,需要找到等價(jià)性最前面的n個元素但又不必對這n個元素進(jìn)行排序,那么,nth_element正是你所需要的函數(shù)。
              如果需要將一個標(biāo)準(zhǔn)序列容器中的元素按照是否滿足某個特定的條件區(qū)分開來,那么,partition和stable_partition可能正是你所需要的。
              如果你的數(shù)據(jù)在一個list中,那么你仍然可以直接調(diào)用partition和stable_partition算法;可以用list::sort來替代sort和stable_sort算法。但是,如果你需要獲得partial_sort或nth_element算法的效果,那么,正如前面我所提到的那樣,你可以有一些簡潔的途徑來完成這項(xiàng)任務(wù)。

            3。如果確實(shí)需要刪除元素,則需要在remove這一類算法之后調(diào)用erase。

               remove不是真正意義上的刪除,因?yàn)樗霾坏健?br />
            4.對包含指針的容器使用remove這一類算法時(shí)要特別小心。會導(dǎo)致資源泄露。

            5.了解哪些算法要求使用排序的區(qū)間作為參數(shù)。

            6.通過mismatch或lexicographical_compare實(shí)現(xiàn)簡單地忽略大小寫的字符串比較

            7.理解copy_if算法的正確實(shí)現(xiàn)

            8.使用accumlate或者for_each進(jìn)行區(qū)間統(tǒng)計(jì)。

            posted @ 2014-06-25 17:06 Daywei 閱讀(1453) | 評論 (0)編輯 收藏

            2014年6月13日

            Effective STL(4)——迭代器

            1.iterator 優(yōu)先于const_iterator、reverse_iterator及const_reverse_iterator

            2.使用distance和advace將容器的const_iterator轉(zhuǎn)換成iterator

            3.正確理解由reverse_iterator的base()成員函數(shù)所產(chǎn)生的iterator的用法。

            4.對于逐個字符的輸入請考慮使用istreambuf_iterator

            posted @ 2014-06-13 15:00 Daywei 閱讀(1281) | 評論 (0)編輯 收藏

            2014年5月16日

            Effective STL(3)——關(guān)聯(lián)容器

            1.理解相等(equality)和等價(jià)(equivalence)的區(qū)別

            相等的概念是基于operator==的。等價(jià)關(guān)系是以“在已排序的區(qū)間中對象值得相對順序”為基礎(chǔ)的。如果從每個標(biāo)準(zhǔn)關(guān)聯(lián)容器的排列順序來考慮等價(jià)關(guān)系,那么著將是有意義的。標(biāo)準(zhǔn)關(guān)聯(lián)容器室基于等價(jià)而不是相等的。標(biāo)準(zhǔn)關(guān)聯(lián)容器總是保持排列順序的,所以每個容器必須有一個比較函數(shù)(默認(rèn)less)來決定保持怎樣的順序。等價(jià)是按照比較函數(shù)子。因此,標(biāo)準(zhǔn)關(guān)聯(lián)容器的使用者要為所使用的每個容器指定一個比較函數(shù)(用來決定如何排序)。如果該關(guān)聯(lián)容器使用相等來決定兩個對象是否有相同的值,那么每個關(guān)聯(lián)容器除了用于排序的比較函數(shù)外,還需要另一個比較函數(shù)來決定兩個值是否相等(默認(rèn)情況下,該比較函數(shù)應(yīng)該是equal_to,但有趣的是equal_to從來沒有被用做STL的默認(rèn)比較函數(shù)。當(dāng)STL中需要相等判斷時(shí),一般的慣例是直接調(diào)用operator==。比如,非成員函數(shù)find算法就是這么做的)

            2.為包含指針的關(guān)聯(lián)容器指定比較類型

            why?第一條已經(jīng)說明關(guān)聯(lián)容器是要排序。每當(dāng)你要創(chuàng)建包含指針的關(guān)聯(lián)容器時(shí),一定要記住,容器將會按照指針的值進(jìn)行排序。一般是不是你希望的,所以你幾乎要創(chuàng)建自己的函數(shù)子類作為該容器的比較類型。

            3.總是讓比較函數(shù)在等值情況下返回false

            比較函數(shù)的返回值表明的是按照該函數(shù)定義的排列順序,一個值是否在另一個之前。相等的值從來不會有前后順序關(guān)系,所以,對于相等的值,比較函數(shù)應(yīng)該始終返回false。

            4.切勿直接修改set或multiset中的鍵。

            5。考慮用排序的vector替代關(guān)聯(lián)容器

            在排序的vector中存儲數(shù)據(jù)可能比在標(biāo)準(zhǔn)關(guān)聯(lián)容器中存儲同樣的數(shù)據(jù)要耗費(fèi)更少的內(nèi)存,而考慮到頁面錯誤的因素,通過二分搜索法來查找一個排序的vector可能比查找一個標(biāo)準(zhǔn)關(guān)聯(lián)容器要更快一些。

            6.當(dāng)效率至關(guān)重要時(shí),請?jiān)趍ap::operator[]與map::insert之間謹(jǐn)慎做出選擇

            map::operator[]的設(shè)計(jì)目的是為了提供“添加和更新”的功能。添加一個新元素最好選后者insert。

            7.熟悉非標(biāo)準(zhǔn)的散列容器。

            posted @ 2014-05-16 16:30 Daywei 閱讀(1344) | 評論 (0)編輯 收藏

            僅列出標(biāo)題  下一頁
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            文章檔案

            牛人博客

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            久久国产精品久久精品国产| 久久精品国产99国产精品导航 | 久久无码专区国产精品发布 | 久久国产免费观看精品| 伊人久久无码中文字幕| 久久久这里只有精品加勒比| 色婷婷久久综合中文久久一本| 久久成人精品| 色播久久人人爽人人爽人人片aV| 久久久久亚洲av成人无码电影| 国产69精品久久久久99| 久久99精品久久久久久水蜜桃| 久久国产综合精品五月天| 久久精品亚洲乱码伦伦中文| 久久久久国产一区二区三区| 久久国产精品免费一区| 思思久久99热只有频精品66| 四虎国产精品成人免费久久| 影音先锋女人AV鲁色资源网久久| 久久综合久久自在自线精品自| 久久偷看各类wc女厕嘘嘘| 久久精品国产亚洲一区二区| 超级碰久久免费公开视频| 色综合久久久久综合99| 久久精品国产亚洲av麻豆图片| 久久久久久国产精品无码超碰| 91久久婷婷国产综合精品青草| 国产精品伊人久久伊人电影| 99久久国产亚洲综合精品| 久久亚洲AV成人无码电影| 精品久久人人做人人爽综合| 久久久国产视频| 久久亚洲综合色一区二区三区| 久久亚洲精品无码播放| 久久夜色精品国产噜噜噜亚洲AV | 久久久久久曰本AV免费免费| 97热久久免费频精品99| 久久青青国产| 婷婷久久综合九色综合98| 久久久精品国产| 久久精品亚洲乱码伦伦中文 |