pos機初始化失敗103

 新聞資訊2  |   2023-07-25 11:54  |  投稿人:pos機之家

網上有很多關于pos機初始化失敗103,C++11 精要學習的知識,也有很多人為大家解答關于pos機初始化失敗103的問題,今天pos機之家(www.www690aa.com)為大家整理了關于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、pos機初始化失敗103

pos機初始化失敗103

引言

變量初始化的工作,要是不細想,可能會覺得是一件挺簡單的事兒,例如int a = 100;。但在 C++ 的世界里,誰也不敢說哪件事是簡單的,要是寫成int a = {100};,不知道你有沒有見過?

其實后一種寫法是列表初始化方法,是 C++11 標準里定義的,它的結果也和前一種一樣。我們在下文會對列表初始化的用法、原理,以及如何避坑進行詳細討論。

如果這個變量int a是出現在類的聲明中,那又有什么新花樣對它進行默認初始化呢?我們就從類的非靜態成員默認初始化說起吧。

非靜態成員默認初始化

這要從一個痛點說起。

在 C++11 標準之前,如果一個類的非靜態數據成員較多,那么用初始化列表方式,編寫構造函數時就會比較痛苦。如下例所示,會發現這幾乎就是在窮舉各種情況。

class OneInit { public: OneInit() : x(0), y(false), z("init") {} OneInit(int x) : x(x), y(false), z("init") {} OneInit(bool y) : x(0), y(y), z("init") {} OneInit(const string &z) : x(0), y(0), z(z) {} private: int x; bool y; string z;};

這還僅是舉個栗子,實際情況里一個類里十來個成員是常有的事,真要這樣寫默認初始化,費勁不說,還容易出錯。

C++11 提供了新的初始化方法,就是在類內聲明處,直接對非靜態成員賦值即可。經過改寫,看下新的版本:

class OneInit { public: OneInit() {} OneInit(int x) : x(x) {} OneInit(bool y) : y(y) {} OneInit(const string &z) : z(z) {} private: int x = 0; bool y = false; string z{"init"}; //這是列表初始化方法,下節會具體講述};

是不是簡化得多了,是不是有一種清爽感撲面而來?構造函數里,只關注你想初始化的成員就好,所有默認值都可以放在聲明處,一次性解決。

雖然方便,但仍有兩點注意事項,以免掉坑。

第一,不要使用括號()對非靜態數據成員進行初始化;第二,不要使用auto關鍵字聲明和初始化非靜態數據成員。

其實你真用了上面的方法,編譯也會報錯,只是要知道錯在哪里。

列表初始化

在介紹列表初始化之前,我們先回顧一下已有的兩種初始化方式:直接初始化和拷貝初始化。

直接初始化一般使用括號方式,將初始值賦予變量。而拷貝初始化,則是使用等號對變量進行初始化。

示例代碼如下:

class OneInit { public: OneInit(int x) {}};int main() { OneInit one(100); // 直接初始化 OneInit one2 = 101; // 拷貝初始化 OneInit *one3 = new OneInit(102); // 思考題:這是哪種初始化類型?}

需要注意的是,拷貝初始化的等號并不是賦值的含義,而是隱式調用構造函數。如果在構造函數前加上explicit關鍵字,則編譯會失敗。explicit的作用就是強制構造函數必須顯式調用。

那么,我們來看一下 C++11 中新增的列表初始化的方法,它使用花括號{}對變量進行初始化。列表初始化也有直接和拷貝兩種初始化類型。

還是用代碼說話:

class OneInit { public: OneInit(int x, string y) {}};int main() { OneInit one{100, "init"}; // 直接初始化 OneInit one2 = {101, "init"}; // 拷貝初始化 OneInit *one3 = new OneInit{102, "init"}; // 直接初始化,知道上面思考題的答案了吧}

上述代碼在構造函數中增加了一個string類型參數,以方便大家看到,在多參數的情況下,如何編寫列表初始化方法。

乍一看,這似乎和括號初始化方式差別不大,但它有一個妙用,就是在使用函數返回對象的時候,可以用列表初始化方式進行多參數的隱式構造,看代碼來體會一下:

class OneInit { public: OneInit(int x, string y) {}};OneInit get_object() { return {103, "init"}; // 簡化了生成對象的過程}int main() { OneInit one = get_object();}

相信大家對列表初始化的規則已經了解,下面我們講一個高階應用。

容器初始化

我們對于數組可以方便地以int array[] = {1, 2, 3};這樣的方法來初始化。但是對于 STL 庫中的眾多容器,以前卻沒什么好辦法,只能寫一個循環不斷地追加值。

現在借助于列表初始化,我們也可以做到像數組一樣初始化容器對象了。

int main() { int array1[]{1, 2, 3}; int array2[] = {1, 2, 3}; vector<int> v1{1, 2, 3}; vector<int> v2 = {1, 2, 3}; list<int> l1{1, 2, 3}; list<int> l2 = {1, 2, 3}; map<string, int> m1{ {"one", 1}, {"two", 2}, {"three", 3} }; map<string, int> m2 = { {"one", 1}, {"two", 2}, {"three", 3} };}

STL 容器對象的初始化,看起來也如絲般光滑了。這個實現離不開一個前提,就是容器類要支持std::initializer_list為形參的構造函數。

std::initializer_list是一個支持begin, end, size成員函數的類模板。編譯器首先將花括號的內容構造為一個std::initializer_list對象,然后匹配容器類的構造函數,只要形參是std::initializer_list類型,那么執行相應的構造函數。

在構造函數中對begin, end范圍內的數據進行循環,就實現了多參數元素的初始化。說起來真不復雜,各位有心的完全可以自己定義一個類,然后支持std::initializer_list形參的構造函數,也能實現自有的列表初始化方法了。

不知道你注意到沒有,map 的初始化有點與眾不同,對于多參數的元素,似乎只管嵌套就完了。如果深究的話,你會發現內層元素{"one", 1}其實是隱式調用了std::pair構造函數,而外層則是走的std::initializer_list方式。

注意事項

列表初始化容易掉坑的地方,就是在隱式縮窄轉換上。例如int a = 10240; char b = a;中,變量 b 的初始化就發生了隱式縮窄,信息發生了丟失。這種問題編譯時有可能警告都不會有,所以要千萬小心。

要避免這樣的問題,需要知道四條隱式縮窄規則:

從浮點類型轉換到整數類型;從long double轉換到long或float。或從double轉換到float;從整數類型或非強枚舉類型,轉換到浮點類型;從整數類型或非強枚舉類型,轉換到不能代表所有原始類型值的整數類型。

以下代碼是錯誤示例,請仔細看:

int main() { int a = 10240; double b = 99.9; int c = {3.0}; // 對應規則1 float d = {b}; // 對應規則2 float e = {a}; // 對應規則3 char f = {a}; // 對應規則4}結語

沒想到一個變量初始化,也能整出這么多說法來。即使是一件看起來應該簡單的事情,在 C++ 里面也能不斷挖出坑來。所以誰也不敢說自己是 C++ 高手,那是分分鐘被打臉。

不管怎樣,讓我們記住本文最重要的三個點,方便自己以后寫代碼吧:

類的非靜態成員,可以在聲明處直接初始化;使用列表初始化方法,簡化多參數構造函數隱式執行;STL 容器對象,可直接使用列表初始化方法。

參考資料:

謝丙堃 現代C++語言核心特性解析 人民郵電出版社

以上就是關于pos機初始化失敗103,C++11 精要學習的知識,后面我們會繼續為大家整理關于pos機初始化失敗103的知識,希望能夠幫助到大家!

轉發請帶上網址:http://www.www690aa.com/newsone/89408.html

你可能會喜歡:

版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 babsan@163.com 舉報,一經查實,本站將立刻刪除。