目錄 1php
1. 前言 1linux
2. 安裝日期 1ios
3. GCC國內鏡像下載地址 2c++
4. GCC的依賴庫 2算法
4.1. gmp庫 2express
4.2. mpfr庫 2多線程
4.3. mpc庫 2閉包
4.4. m4編譯工具 2併發
4.5. 安裝源代碼包 3ide
5. 編譯安裝gmp 3
6. 編譯安裝mpfr 4
7. 編譯安裝mpc 4
8. 設置LD_LIBRARY_PATH 4
9. 編譯安裝gcc 4
10. 編譯安裝m4 6
附1:cmake支持 6
附2:debug STL 7
附3:體驗C++14 7
附4:體驗C++17 9
附5:C++標準 11
附6:C++標準當前狀態 12
爲體驗C++17和C++20特性,需安裝更新版本的GCC編譯器。GCC官網爲:https://gcc.gnu.org/,從這裏能夠下載最新版本的GCC。
C++由Bjarne Stroustrup(被譽爲C++之父)於1979年在新澤西州美利山貝爾實驗室開始設計開發的,最初命名爲帶類的C,後來在1983年改名爲C++。
2019/4/27,截至該日期最新版本爲GCC-8.3.0,但在本月未或下月初即將發佈GCC-9.1(已於2019-05-03發佈)。
下載速度不一,請選擇速度最快的:
1) http://mirrors.nju.edu.cn/gnu/gcc/gcc-8.3.0/
2) http://mirrors.ustc.edu.cn/gnu/gcc/gcc-8.3.0/
3) https://mirrors.tuna.tsinghua.edu.cn/gnu/gcc/gcc-8.3.0/
編譯以前需先安裝好GCC的依賴庫:gmp、mpfr和mpc。編譯還依賴m4等編譯工具,若是沒有,則在執行configue時會報相應的錯誤,這時須要先安裝好這些編譯工具。
GMP爲「GNU MP Bignum Library」的縮寫,是一個GNU開源數學運算庫。本文選擇的是最新版本gmp-6.1.2,國內鏡像下載地址:
1) https://mirrors.tuna.tsinghua.edu.cn/gnu/gmp/
2) http://mirrors.nju.edu.cn/gnu/gmp/
3) http://mirrors.ustc.edu.cn/gnu/gmp/
mpfr是一個GNU開源大數運算庫,它依賴gmp。本文選擇的是最新版本mpfr-4.0.2,國內鏡像下載地址:
1) https://mirrors.tuna.tsinghua.edu.cn/gnu/mpfr/
2) http://mirrors.nju.edu.cn/gnu/mpfr/
3) http://mirrors.ustc.edu.cn/gnu/mpfr/
mpc是GNU的開源複雜數字算法,它依賴gmp和mpfr。本文選擇的是最新版本mpc-1.1.0,國內鏡像下載地址:
1) https://mirrors.tuna.tsinghua.edu.cn/gnu/mpc/
2) http://mirrors.nju.edu.cn/gnu/mpc/
3) http://mirrors.ustc.edu.cn/gnu/mpc/
本文選擇的是最新版本m4-1.4.16,下載地址:
1) https://mirrors.tuna.tsinghua.edu.cn/gnu/m4/
2) http://mirrors.nju.edu.cn/gnu/m4/
3) http://mirrors.ustc.edu.cn/gnu/m4/
若是使用「--prefix」指定了安裝目錄,則在編譯gmp等以前還需先設置好環境變量PATH,以便configure時能找到m4。
涉及到的全部安裝源代碼包:
gcc-8.3.0.tar.gz mpfr-4.0.2.tar.gz gmp-6.1.2.tar.xz mpc-1.0.3.tar.gz |
GCC的依賴庫間還互有依賴:mpfr依賴gmp、mpc依賴gmp和mpfr,因此GCC的編譯安裝順序爲:
1) m4(若是須要)
2) gmp
3) mpfr
4) mpc
5) GCC
爲了避免污染已有的編譯和運行環境,將GCC及依賴庫均安裝到/usr/local目錄,而且最好以root用戶完成下述全部操做。
執行configure生成Makefile時,須要用到m4,通常路徑爲/usr/bin/m4,若是沒有則須要先安裝,不然報錯「no usable m4」錯誤,手工安裝m4從「https://www.gnu.org/software/m4/」下載。
具體安裝步驟以下:
xz -d gmp-6.1.2.tar.xz tar xf gmp-6.1.2.tar cd gmp-6.1.2 ./configure --prefix=/usr/local/gmp-6.1.2 make make install ln -s /usr/local/gmp-6.1.2 /usr/local/gmp |
詳細安裝步驟以下:
tar xzf mpfr-4.0.2.tar.gz cd mpfr-4.0.2 ./configure --prefix=/usr/local/mpfr-4.0.2 --with-gmp=/usr/local/gmp make make install ln -s /usr/local/mpfr-4.0.2 /usr/local/mpfr |
tar xzf mpc-1.1.0.tar.gz cd mpc-1.1.0 ./configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp --with-mpfr=/usr/local/mpfr make make install ln -s /usr/local/mpc-1.1.0 /usr/local/mpc |
在編譯GCC以前,若是不設置LD_LIBRARY_PATH(若是編譯gmp時沒有指定「--prefix」時安裝,通常不用再顯示設置),則可能編譯時報「error while loading shared libraries: libmpfr.so.6: cannot open shared object file: No such file or directory」等錯誤。
export LD_LIBRARY_PATH=/usr/local/gmp/lib:/usr/local/mpfr/lib:/usr/local/mpc/lib:$LD_LIBRARY_PATH |
在執行make編譯GCC時,有些費時,請耐心等待。在一臺Intel Xeon 2.30GHz的48核128GB內存機器上花費228分鐘(將近4個小時,同臺機器編譯9.1.0花費190分鐘),編譯GCC-8.3.0的GCC版本爲4.8.5(64位)。
tar xzf gcc-8.3.0.tar.gz cd gcc-8.3.0 ./configure --prefix=/usr/local/gcc-8.3.0 --with-mpfr=/usr/local/mpfr --with-gmp=/usr/local/gmp --with-mpc=/usr/local/mpc date;time make;date make install ln -s /usr/local/gcc-8.3.0 /usr/local/gcc export PATH=/usr/local/gcc/bin:$PATH export LD_LIBRARY_PATH=/usr/local/gcc/lib64:$LD_LIBRARY_PATH export MANPATH=/usr/local/gcc/share/man:$MANPATH gcc --version |
在執行configure時,若是遇到錯誤「I suspect your system does not have 32-bit development libraries (libc and headers). If you have them, rerun configure with --enable-multilib. If you do not have them, and want to build a 64-bit-only compiler, rerun configure with --disable-multilib」,表示系統不支持32位程序,這樣在執行configure時需爲它支持參數「--disable-multilib」,如:
./configure --prefix=/usr/local/gcc-8.3.0 --with-gmp=/usr/local/gmp --with-mpfr=/usr/local/mpfr --with-mpc=/usr/local/mpc --disable-multilib |
若是make時遇到錯誤「internal compiler error」,多是由於內存不足,請換臺內存更大的機器,或者更換GCC版本試試。
若是遇到錯誤「C compiler cannot create executables」、「error while loading shared libraries: libmpfr.so.6: cannot open shared object file: No such file or directory」或「cannot compute suffix of object files」,可嘗試設置LD_LIBRARY_PATH後再試試:
export LD_LIBRARY_PATH=/usr/local/gmp/lib:/usr/local/mpfr/lib:/usr/local/mpc/lib:$LD_LIBRARY_PATH |
make成功結束時的輸出:
make[8]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/32/libatomic」 make[7]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/32/libatomic」 make[6]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/32/libatomic」 make[5]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/libatomic」 make[4]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/libatomic」 make[3]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/libatomic」 make[2]: 離開目錄「/data/GCC/gcc-8.3.0/x86_64-pc-linux-gnu/libatomic」 make[1]: 離開目錄「/data/GCC/gcc-8.3.0 |
在完成上列步驟後,檢查新安裝的GCC-8.3.0是否可用:
# gcc --version gcc (GCC) 8.3.0 Copyright © 2018 Free Software Foundation, Inc. 本程序是自由軟件;請參看源代碼的版權聲明。本軟件沒有任何擔保; 包括沒有適銷性和某一專用目的下的適用性擔保。
# man gcc|col -b|grep c++17 c++17 GNU dialect of -std=c++17. The name gnu++1z is deprecated. This flag is enabled by default for -std=c++17. arguments as an argument for a template template parameter with fewer template parameters. This flag is enabled by default for -std=c++17. adopted for C++17. Enabled by default with -std=c++17. -fstrong-eval-order=some enables just the ordering of member access and shift expressions, and is the default without -std=c++17. -Wc++17-compat. "register" keyword as storage class specifier has been deprecated in C++11 and removed in C++17. Enabled by default with -std=c++17. -Wc++17-compat (C++ and Objective-C++ only) |
已經支持C++20標準,但由於標準還未正式發佈,因此正式發佈後大機率發生變化:
# man gcc|col -b|grep c++2a c++2a GNU dialect of -std=c++2a. Support is highly experimental, and will almost certainly change in incompatible ways in future releases (支持是高度實驗性的,而且在未來的版本中幾乎確定會以不兼容的方式發生變化). |
只有m4不可用或版本太低時才需安裝m4(通常路徑爲/usr/bin/m4),若是configure時不指定prefix,則可省去export和ln兩步:
tar xzf m4-1.4.16 cd m4-1.4.16 ./configure --prefix=/usr/local/m4-1.4.16 make make install ln -s /usr/local/m4-1.4.16 /usr/local/m4 export PATH=/usr/local/m4/bin:$PATH |
在使用cmake前,需設置好下列所環境變量,不然cmake仍將使用默認目錄下的gcc和g++,在CMakeFiles.txt文件中設置CMAKE_C_COMPILER和CMAKE_CXX_COMPILER不能解決這個問題。若是在此以前已經執行過cmake,則得先刪除CMakeFiles目錄和文件CMakeCache.txt,而後再從新執行cmake生成Makefile文件。
export CC=/usr/local/gcc/bin/gcc export CXX=/usr/local/gcc/bin/g++ export PATH=/usr/local/gcc/bin:$PATH export LD_LIBRARY_PATH=/usr/local/gcc/lib64:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=/usr/local/gmp/lib:/usr/local/mpfr/lib:/usr/local/mpc/lib:$LD_LIBRARY_PATH |
有時須要debug STL中的容器等,正常狀況下無法跟蹤STL中的代碼,只須要加上編譯宏「_GLIBCXX_DEBUG」便可開啓對STL的debug。注意這個並非GCC編譯器定義的,而是直接在STL源代碼中定義的。細心點可發如今STL庫頭文件目錄中有一個debug子目錄,以4.8.5爲例:
$ ls /usr/include/c++/4.8.5/debug array deque functions.h map multiset.h safe_iterator.tcc safe_sequence.h safe_unordered_container.h set.h unordered_set bitset formatter.h list map.h safe_base.h safe_local_iterator.h safe_sequence.tcc safe_unordered_container.tcc string vector debug.h forward_list macros.h multimap.h safe_iterator.h safe_local_iterator.tcc safe_unordered_base.h set unordered_map |
查看正常的文件,便可看到「_GLIBCXX_DEBUG」:
$ vi /usr/include/c++/4.8.5/map
#ifdef _GLIBCXX_DEBUG # include <debug/map> #endif
#ifdef _GLIBCXX_PROFILE # include <profile/map> #endif |
// C++14 #include <iostream>
[[deprecated]] auto foo1() { int m = 2019; return m; }
[[deprecated("foo2 is deprecated")]] auto foo2() { int m = 2020; return m; }
int main() { const auto n1 = foo1(); const auto n2 = foo2(); std::cout << "n1: " << n1 << std::endl << "n2: " << n2 << std::endl; return 0; } |
編譯運行結果以下:
$g++ -o main *.cpp main.cpp: In function ‘int main()’: main.cpp:17:24: warning: ‘auto foo1()’ is deprecated [-Wdeprecated-declarations] const auto n1 = foo1(); ^ main.cpp:5:6: note: declared here auto foo1() { ^~~~ main.cpp:18:24: warning: ‘auto foo2()’ is deprecated: foo2 is deprecated [-Wdeprecated-declarations] const auto n2 = foo2(); ^ main.cpp:11:6: note: declared here auto foo2() { ^~~~ $main n1: 2019 n2: 2020 |
若是在C++11上編譯,會報語法錯誤:
main.cpp:5:11: error: 'foo1' function uses 'auto' type specifier without trailing return type auto foo1() { ^ main.cpp:5:11: note: deduced return type only available with -std=c++14 or -std=gnu++14 main.cpp:11:11: error: 'foo2' function uses 'auto' type specifier without trailing return type auto foo2() { ^ main.cpp:11:11: note: deduced return type only available with -std=c++14 or -std=gnu++14 main.cpp: In function 'int main()': main.cpp:17:24: warning: 'auto foo1()' is deprecated [-Wdeprecated-declarations] const auto n1 = foo1(); ^ main.cpp:5:6: note: declared here auto foo1() { ^~~~ main.cpp:17:24: warning: 'auto foo1()' is deprecated [-Wdeprecated-declarations] const auto n1 = foo1(); ^ main.cpp:5:6: note: declared here auto foo1() { ^~~~ main.cpp:18:24: warning: 'auto foo2()' is deprecated: foo2 is deprecated [-Wdeprecated-declarations] const auto n2 = foo2(); ^ main.cpp:11:6: note: declared here auto foo2() { ^~~~ main.cpp:18:24: warning: 'auto foo2()' is deprecated: foo2 is deprecated [-Wdeprecated-declarations] const auto n2 = foo2(); ^ main.cpp:11:6: note: declared here auto foo2() { ^~~~ |
// C++17 #include <iostream>
template <auto v> auto foo() { return v; }
int main() { std::cout << "foo return: " << foo<2019>() << std::endl; for (int i=0; i<10; ++i) { if (int m=i%2;0==m) std::cout << "i: " << i << std::endl; } return 0; } |
編譯運行結果以下:
foo return: 2019 i: 0 i: 2 i: 4 i: 6 i: 8 |
再體驗一段來源於http://www.modernescpp.com/index.php/functional-in-c-17-and-c-20的C++17代碼:
// foldExpression.cpp #include <iostream>
template<typename... Args> bool all(Args... args) { return (... && args); } template<typename... Args> bool any(Args... args) { return (... || args); } template<typename... Args> bool none(Args... args) { return not(... || args); }
int main(){ std::cout << std::endl; std::cout << std::boolalpha; std::cout << "all(true): " << all(true) << std::endl; std::cout << "any(true): " << any(true) << std::endl; std::cout << "none(true): " << none(true) << std::endl; std::cout << std::endl; std::cout << "all(true, true, true, false): " << all(true, true, true, false) << std::endl; std::cout << "any(true, true, true, false): " << any(true, true, true, false) << std::endl; std::cout << "none(true, true, true, false): " << none(true, true, true, false) << std::endl; std::cout << std::endl; std::cout << "all(false, false, false, false): " << all(false, false, false, false) << std::endl; std::cout << "any(false, false, false, false): " << any(false, false, false, false) << std::endl; std::cout << "none(false, false, false, false): " << none(false, false, false, false) << std::endl; std::cout << std::endl; } |
編譯運行結果以下:
all(true): true any(true): true none(true): false
all(true, true, true, false): false any(true, true, true, false): true none(true, true, true, false): false
all(false, false, false, false): false any(false, false, false, false): false none(false, false, false, false): true |
可瀏覽https://en.cppreference.com/w/cpp/compiler_support瞭解各編譯器對C++標準的支持詳情。C++標準官網:https://isocpp.org/。
年份 |
C++標準 |
名稱 |
__cplusplus值 |
重大新特性 |
1998 |
ISO/IEC 14882:1998 |
C++98 |
199711L |
第一個C++標準 |
2003 |
ISO/IEC 14882:2003 |
C++03 |
199711L |
第二個C++標準 |
2011 |
ISO/IEC 14882:2011 |
C++11 |
201103L |
第三個C++標準 1) auto關鍵字 2) 右值引用 3) nullptr關鍵字 4) shared_ptr/unique_ptr/weak_ptr 5) long long 6) lambda(相似JS的閉包) 7) decltype 8) constexpr 9) delete/default 10) final/override 11) noexcept 12) std::tuple 13) std::move 14) 變長參數的模板 15) 模板「>>」(兩個「>」間再也不需空格) 16) 多線程併發支持:thread_local、std::atomic、std::thread等 |
2014 |
ISO/IEC 14882:2014 |
C++14 |
201402L |
第四個C++標準 1) 函數可返回auto(返回值類型推導) 2) 泛型lambda 3) deprecated屬性 4) std::optional 5) 二進制常量和數字分隔符 |
2017 |
ISO/IEC 14882:2017 |
C++17 |
201703L |
第五個C++標準 1) 刪除三字符詞(如「??=」、「??-」等) 2) if/switch語句內可定義和初始化變量 3) std::any/std::variant 4) 內聯變量(可在頭文件中定義變量) 5) __has_include 6) 並行STL 7) 摺疊表達式(fold expression) 8) 構造函數的模板推導(class template deduction) 9) 結構化綁定(structured bindings) |
2020 |
暫未定 |
C++20 |
|
第六個C++標準(暫未正式發佈): 1) 協程(coroutines) 2) 模塊化(modules) 3) Concepts(編譯期模板) 4) Ranges |
|
未定 |
C++23 |
|
|
|
|
C++26 |
|
|
注:TS爲「Technical Specifications」的縮寫,IS爲「International Standard」的縮寫,TR爲「Technical Report」的縮寫。