速学c++(3)-函数
函數
實戰
#include <iostream> int myAdd(int,int); int main() {int x=10;int y=20;std::cout<<x<<"+"<<y<<"="<<myAdd(x,y)<<std::endl;return 0; } int myAdd(int x,int y) {return x+y; }要點
1.函數調用
2.函數參數
3.函數返回
lambda匿名函數
實戰
#include <iostream>auto myAdd= [](int x, int y) { return x+y;};// 隱式返回類型 int main() {int x1=10;int x2=20;std::cout<<x1<<"+"<<x2<<"="<<myAdd(x1,x2)<<std::endl;return 0; }要點
1.auto可以在聲明變量的時候根據變量初始值的類型自動為此變量選擇匹配的類型。
2.編譯程序的命令(即加上編譯選項-std=c++11,表示使用c++11標準,因為本例遵守c++11標準,比如:auto、匿名函數myAdd):
g++ “/Users/deepmyhaspl/docs/teacher/c++/learn-1/1-3/main.cpp” -std=c++11 -o ./myprogram -I. -I.
或者直接在CodeLite中勾選
[外鏈圖片轉存失敗(img-Vy9mrBx7-1568294615375)(/Users/deepmyhaspl/docs/teacher/c++/1_1.png)]
capture->return-type{body}
也可以如下定義myAdd
[](int x, int y) -> int { int z = x + y; return z; } [] //未定義變量.試圖在Lambda內使用任何外部變量都是錯誤的. [x, &y] //x 按值捕獲, y 按引用捕獲. [&] //用到的任何外部變量都隱式按引用捕獲 [=] //用到的任何外部變量都隱式按值捕獲 [&, x] //x顯式地按值捕獲. 其它變量按引用捕獲 [=, &z] //z按引用捕獲. 其它變量按值捕獲capture表示捕捉變量
#include <iostream> int main() {int x1=10;int x2=20;auto mySwap=[&x1,&x2]() { auto temp=x1;x1=x2;x2=temp;};mySwap();std::cout<<x1<<std::endl;std::cout<<x2<<std::endl;return 0; } #include <iostream> int main() {int x1=10;int x2=20;auto mySwapAdd=[&x1,&x2](int y) { auto temp=x1;x1=x2;x2=temp;x1+=y;x2+=y;};mySwapAdd(5);std::cout<<x1<<std::endl;std::cout<<x2<<std::endl;return 0; } #include <iostream> //使用C++14標準編譯,因為myAdd這個函數變量(為函數對象)是一個變量模板。 template<typename T> auto myAdd=[](T x,T y) { return x+y;}; int main() {int x1=10;int x2=20;std::cout<<myAdd<int>(x1,x2)<<std::endl;return 0; } #include <iostream> template<typename T> T var;//變量模板 int main() {var<int> =10;var<double> =20.364;std::cout<< var<int> <<" "<< var<double> <<std::endl;return 0; }constexpr函數
c++11標準
如果函數可能在編譯時求值,則聲明它為constexpr,以提高效率。需要使用constexpr告訴編譯器允許編譯時計算。
constexpr不保證編譯時一定計算。如果需要保證,可在編譯時對常量表達式參數求值。
constexpr int min(int x, int y) { return x < y ? x : y; } void test(int v) {int m1 = min(-1, 2); // 可能在編譯期計算constexpr int m2 = min(-1, 2); // 編譯時計算int m3 = min(-1, v); // 運行時計算constexpr int m4 = min(-1, v); // 錯誤,不能在編譯期計算 }不要試圖使所有的函數都是常量。大多數計算最好在運行時完成。
任何可能最終依賴于高級運行時或業務邏輯的API都不應該成為constexpr。編譯器無法計算這種定制,依賴于該API的任何constexpr函數都必須被重構或刪除。
int dcount = 0; constexpr int double(int v) {++dcount; // constexpr 函數無副作用,因為這一行錯誤return v + v; } constexpr int factorial (int n) {return n > 0 ? n * factorial( n - 1 ) : 1; }內聯函數
要點
內聯函數通常一段短小的程序。類中定義的成員函數在默認情況下是內聯的。inline是修飾內聯函數的,內聯提高程序調用簡單函數的速度。內聯不能遞歸,下面程序是錯誤的!
inline int factorial (int n) { return n > 0 ? n * factorial( n - 1 ) : 1;//error! }- constexpr函數被隱式地指定為內聯函數。
- constexpr允許遞歸。
可選屬性列表(C++11)
可選的屬性列表。這些屬性應用于函數類型,而非函數自身。出現于聲明器中標識符之后的屬性會與出現于聲明開端的屬性合并,若它們存在。
1)簡單屬性,如[[noreturn]]
2)具有名稱空間的屬性,如 [[gnu::unused]]
3)帶參數的屬性,如[[deprecated(“because”)]]
4)屬性,具有名稱空間和參數列表
屬性為實現定義的語言擴展提供統一的標準語法,例如GNU和IBM語言擴展__attribute__((…))、Microsoft擴展__declspec()等。
在c++程序中,幾乎在任何地方都可以使用一個屬性,并且可以適用于幾乎所有:類型,變量,函數,名稱,代碼塊,整個轉換單元,雖然每個特定屬性只在允許有效的實現:[[expect_true]]可以是一個屬性,只能使用if,而不是一個類聲明。[[omp::parallel()]]可以是應用于代碼塊或for循環的屬性,但不應用于int類型等。
在聲明中,屬性可以出現在整個聲明之前,也可以直接出現在聲明的實體名稱之后,在這種情況下,屬性是組合在一起的。在大多數其他情況下,屬性應用于前面的實體。
alignas說明符是屬性說明符序列的一部分,盡管它有不同的語法。它可能出現在[[…]]屬性出現的地方,并可能與它們混合(如果允許使用alignas)
兩個連續的左方括號令牌([[])只能在引入屬性說明符或屬性參數時出現。
出現于聲明前的屬性和在聲明器中立即出現在標識符后的屬性應用于聲明或定義的同一實體
(1)[[noreturn]]指示函數永不返回(指定函數不會由于執行到 return 語句或抵達函數體結尾而返回,可通過執行 longjmp(c++17)跳轉到指定位置),有助于編譯器進行編譯優化(如尾遞歸等),也可以用于抑制編譯器給出不必要的警告。
屬性可以出現在整個聲明之前,也可以直接出現在聲明的實體名稱之后,而出現于聲明器后(語法上)的屬性,應用到函數類型,而非函數自身。
加載先前的 setjmp調用所保存的執行環境 env 。此函數不返回。控制被轉移到設置了 env 的宏 setjmp的調用點。該 setjmp隨后返回作為 status 傳遞的值。
(2)[[deprecated(“reason”)]]
[[deprecated(string-literal)]]
指示允許使用聲明有此屬性的名稱或實體,但因故不鼓勵使用。編譯器常在這種使用時發出警告。若指定 string-literal ,則它通常被包含于警告中。
# include <iostream> #include <csetjmp> using namespace std; jmp_buf jump_buffer;//std名字空間的,<csetjmp>[[noreturn]]void addNum2[[noreturn]](int &res,int a){res+=a;cout<<"addnum:"<<a<<"="<<res<<endl;longjmp(jump_buffer,a+1); // setjump() 將返回 a+1}void addNum1(int a ,int b,int &res){//注意res是引用方式,即變量別名,相當于傳指針而不是傳值res= a+b; }[[deprecated("dfunc has been deprecated ")]]void dfunc(){cout<<"dfunc"<<endl; }int main(int argc, char **argv) {int x=0;int y[[deprecated("y has been deprecated ")]]=222; addNum1(12,22,x);cout<<x<<endl;cout<<y<<endl;dfunc();volatile int a = 0; // 必須為 setjmp 設定局部變量為 volatileint result=0;if (setjmp(jump_buffer) <= 20) {addNum2(result,++a); } }[[carries_dependency]]指示釋放消費 std::memory_order 中的依賴鏈傳進和傳出該函數,這允許編譯器跳過不必要的內存柵欄指令。
此屬性可在二種情形中出現:
[[fallthrough]](C++17) 指示失敗于以前的一個case標簽,不應該由警告失敗的編譯器診斷
[[nodiscard]](C++17) 如果返回值被丟棄,則鼓勵編譯器發出警告
[[maybe_unused]]`(C++17) 對未使用的實例抑制編譯器警告。
總結
以上是生活随笔為你收集整理的速学c++(3)-函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 速学c++(2)-helloworld工
- 下一篇: Microsoft Visual c++