1. 程式人生 > 其它 >嵌入式軟體開發第一講筆記

嵌入式軟體開發第一講筆記

技術標籤:筆記c++

C+ +概述
1、嵌入式中為什麼需要C+ +?
2、C+ +就業方向
3、C+ +面向物件特點(面向過程VS 面向物件)
4、C++標準(C++98, C++11, C++14, C++17, C++20)
5、C++編譯器(vs微軟VS g++) (名稱空間: vs命名名字:成員) g++
6、名稱空間(作用(命名衝突:全域性變數、函式)、使用注意事項、義使用命名)
7、C++ 輸入輸出(printf )
8、C++關鍵字register. using、 auto (型別推導:高效程式設計) const、 constexpr
9、C++引用(作用、函式形參、返回值、左值、右值引用)指標VS引用

10、C+ +分配空間: new、 delete
11、C+ +對函式的升級(函式過載,行內函數)
12、C+ +型別升級struct- class(類,成員,成員變數,方法(函式))
13、string類

C++在嵌入式開發中地位及應用領域:上層應用軟體(c/c++/java/object c/php、指令碼語言:python)
中間框架(執行庫)(sqlite3、網路執行緒庫、opengl、opencv、tensorflow、caffer框架)
系統:Linux Android (C/彙編/指令碼) Linux核心
底層硬體:ARM 人工智慧晶片(fpga) — 彙編/硬體程式語言

學習C++的意義:C++:c with class:對C語言開發的幫助 面向結構 VS 面向物件

掌握C/C++ :幫助快速學習其他語言
面向物件的思想幫助系統的設計及架構

面向結構 VS 面向物件:
面向結構程式設計:
優點:能夠直接訪問硬體(指標)、執行效率、移植性
缺點:具體任務(具體且簡單的業務邏輯)(複用性(功能複用)、維護性(準確定位)、擴充套件性(需求不斷變化))
面向物件:
優點:複用性(繼承)、維護性(封裝)、擴充套件性(多型)
系統任務(複雜的業務邏輯)
缺點:降低了語言本身的效能

c++對c的加強:
1.名稱空間
2.輸入與輸出
3.實用性加強
4.引用
5.動態分配記憶體(new、delete)

名稱空間的加強:
為什麼要引入名稱空間的概念:為了解決合作開發時的命名衝突問題,C++ 引入了名稱空間(Namespace)的概念。名稱空間將全域性作用域分成不同的部分、不同名稱空間中的識別符號可以同名而不會發生衝突、名稱空間可以相互巢狀、全域性作用域也叫預設名稱空間

名稱空間的定義:namespace 是C++中的關鍵字,用來定義一個名稱空間,語法格式為:
namespace name
{
變數
函式

}
name是名稱空間的名字,它裡面可以包含變數、函式、類、typedef、#define 等,最後由{ }包圍 、名稱空間的定義可以巢狀
namespace NameSpaceB
{
int a = 1;

namespace NameSpaceC
{
    struct Teacher
    {
        char name[10];
        int age;
    };
}

}

名稱空間的使用:1.使用域解析符::
::是一個新符號,稱為域解析操作符,在C++中用來指明要使用的名稱空間。
NameSpaceA::a = 10; // 使用名稱空間 NameSpaceA中的變數a
2.使用using宣告
// 在這裡用using聲明瞭 NameSpaceA::a, 它的意思是在宣告以後的程式中如果出現
// 未指明名稱空間的a,就使用NameSpaceA名稱空間裡的a
// 如果要使用NameSpaceB名稱空間中的a,則仍需要使用這樣的方式 NameSpaceB::a;
using NameSpaceA::a;
a = 20; // 使用名稱空間NameSpaceA中的a
NameSpaceB::a = 30; // 使用名稱空間NameSpaceB中的a
// using 宣告不僅可以針對名稱空間中的變數或者函式,還可以對整個名稱空間進行宣告
// 這樣的方式宣告名稱空間以後,在後面使用未指定具體名稱空間的變數或者函式產生命名衝突的時候
// 預設使用 NameSpaceB中的變數和函式
using namespace NameSpaceB;
a = 10;

printf ("%d\n", NameSpaceB::a);

名稱空間的注意事項:1、原始檔不能訪問其他原始檔的名稱空間(名稱空間中存在定義)
(即時放在標頭檔案裡,然後包含之後都無法訪問)
2、名字空間名稱相同,成員名字不同,那麼他們會自動合併為一個名字空
間,可以理解為追加
3、字空間名稱相同,成員名稱相同。那麼程式會在除錯過程的link時報錯。因
為聯結器會檢測到重複定義的變數。(extern)
一個c++程式中需要注意:1、名稱空間的作用範圍
2、使用規範:將 std 直接宣告在所有函式外部,這樣雖然使用方便,但
在中大型專案開發中是不被推薦的,這樣做增加了命名衝突的風險,推
薦在函式內部宣告 std。

輸入與輸出的加強:c++的I/O發生在流中,流是位元組序列
I/O庫標頭檔案: 該檔案定義了cin、cout、cerr和clog物件
該檔案通過所謂的引數化的流操縱器,來宣告執行標準化
有用的服務
該檔案為使用者控制的檔案處理宣告服務.
標準輸出流cout:預定義的物件 cout 是 iostream 類的一個例項
標準輸入流 cin:預定義的物件 cin 是 iostream 類的一個例項
標準錯誤流 cerr:cerr 是 iostream 類的一個例項、cerr 物件是非緩衝的,且每個流插入到 cerr 都會
立即輸出。
標準日誌流 clog:clog 是 iostream 類的一個例項、clog 物件是緩衝的

實用性加強:
for語句:可以在括號裡直接定義並初始化變數
foreach用法
register關鍵字的變化:register關鍵字請求“編譯器”將區域性變數儲存於暫存器中
C語言中無法取得register變數地址
在C++中依然支援register關鍵字
1、C++編譯器有自己的優化方式,不使用register也可能做優化
2、C++中可以取得register變數的地址
C++編譯器發現程式中需要取register變數的地址時,register對
變數的宣告變得無效。
bool型別關鍵字:C++在C語言的基本型別系統之上增加了bool
C++中的bool可取的值只有true和false
三目運算子的增強:1)C語言返回變數的值
C++語言是返回變數本身
C語言中的三目運算子返回的是變數值,不能作為左值使用
C++中的三目運算子可直接返回變數本身,因此可以出現在程式的
任何地方
2)注意:三目運算子可能返回的值中如果有一個是常量值則不能
作為左值使用
(a < b ? 1 : b )= 30;
3)C語言如何支援類似C++的特性呢?
當左值的條件:要有記憶體空間;
C++編譯器幫助程式設計師取了一個地址而已.
auto關鍵字:C語言auto關鍵字主要強調儲存週期
C++中的auto關鍵字的作用自動推斷變數的型別,通過變數的初始值或者表
達式中參與運算的資料型別來推斷變數的型別
auto定義的變數必須初始化
使用using定義別名(替代typedef):using func_t = void (*)(int, int);

引用:為變數的別名,定義的時候必須初始化繫結一個指定物件,且中途不可更改繫結物件
使用注意事項:引用&初始化的時候,必須要與另外一個變數建立繫結關係。
一旦引用&與某一變數建立繫結關係,這個關係就不會再被改變,
作用:函式傳參、返回值
const升級:C語言只讀變數,C++常量
常引用:不能通過引用去修改繫結值
常量表達式constexpr:
作用:值不會改變並且在編譯過程中就得到計算結果的表達

constexpr函式是指能用於常量表達式的函式
好處:是一種很強的約束,更好地保證程式的正確語義不被
破壞
編譯器可以在編譯期對constexpr的程式碼進行非常大的
優化,比如將用到的constexpr表示式都直接替換成最
終結果等。
相比巨集來說,沒有額外的開銷,但更安全可靠。
指標和引用的區別:本質:引用只能繫結一次,指標可以繫結在任意的變數
記憶體分配:引用不佔用記憶體空間(使用者無法操作),指標佔用記憶體空間(error)!!
!!!引用不是新的資料型別,
級數:指標可以多級指標,引用只能一級(error)!!!右值引用
使用效率:效率,安全性,推薦使用引用
左值、右值、左值引用、右值引用:可以通過&運算子獲取地址的,就是左值;若否就是右值
左引用繫結左值
右引用繫結右值

動態記憶體分配(new、delete):
new、delete使用——二維陣列、陣列指標等分配
new、delete VS malloc free:
new關鍵字是c++的一部分,malloc是有c庫提供的函式
new以具體型別為單位進行記憶體分配,malloc只能以位元組為單位進行記憶體分配
new在申請單個型別變數是課進行初始化,malloc不具備記憶體初始化的特性

c++對c的函式擴充套件:
行內函數:inline是由編譯決定,使用inline關鍵字只是申請編譯器;
限制:行內函數中不可含有迴圈;
行內函數中不可能含有靜態變數;
行內函數不可為遞迴函式;
行內函數中不可含有錯誤處理。
選擇:只將規模很小(一般5個語句一下)而使用頻繁的函式宣告為行內函數。
注意事項:行內函數的定義必須出現在行內函數第一次呼叫之前;
預設引數:C++中可以在函式宣告時為引數提供一個預設值,
當函式呼叫時沒有指定這個引數的值,編譯器會自動用預設值代替
規則:只有引數列表後面部分的引數才可以提供預設引數值
一旦在一個函式呼叫中開始使用預設引數值,那麼這個引數後的所有引數都必須使用默
函式過載:
概念:用同一個函式名定義不同的函式,當函式名和不同的引數搭配時函式的含義不同
函式過載判斷標準: 引數個數不同,引數型別不同,引數順序不同
函式返回值不是函式過載的判斷標準
呼叫函式過載的準則:將所有同名函式作為候選者
嘗試尋找可行的候選函式:
1 )精確匹配實參
2) 通過預設引數能夠匹配實參
3) 通過預設型別轉換匹配實參
匹配失敗:
1) 最終尋找到的可行候選函式不唯一,則出現二義性,
編譯失敗。
2) 無法匹配所有候選者,函式未定義,編譯失敗。
函式過載的注意事項:過載函式在本質上是相互獨立的不同函式(靜態鏈編)
過載函式的函式型別是不同的
函式返回值不能作為函式過載的依據
函式過載是由函式名和引數列表決定的。
函式過載與函式指標:當使用過載函式名對函式指標進行賦值時:
根據過載規則挑選與函式指標引數列表一致的候選者
嚴格匹配候選者的函式型別與函式指標的函式型別

struct結構體升級:
定義與使用
結構體內定義函式
許可權修飾符:public、private—預設public許可權
可繼承
類的概念—class一種新的型別;定義的變數稱為物件
預設private許可權;

string類:
string類的建構函式
string s1;//預設建構函式,s1為空串
string s2(s1);//將s2初始化為s1的副本
string s3(“value”);//將s3初始化為一個字串副本
string s4(n,‘c’);//將s4初始化為字串’c’的n個副本

string類的字元操作
const char &operator[](int n)const;
const char &at(int n)const;
char &operator[](int n);
char &at(int n);
operator[]和at()均返回當前字串中第n個字元的位置,但at函式提供範圍檢查,當越界時會丟擲out_of_range異常,下標運算子[]不提供檢查訪問
int copy(char *s, int n, int pos = 0) const;//把當前串中以pos開始的n個字元拷貝到以s為起始位置的字元陣列中,返回實際拷貝的數目
string類的特性描述
int capacity()const; //返回當前容量(即string中不必增加記憶體即可存放的元素個數)
int max_size()const; //返回string物件中可存放的最大字串的長度
int size()const; //返回當前字串的大小
int length()const; //返回當前字串的長度
bool empty()const; //當前字串是否為空
void resize(int len,char c);//把字串當前大小置為len,並用字元c填充不足的部分
string類的輸入輸出操作
string類過載運算子operator>>用於輸入,同樣過載運算子operator<<用於輸出操作。
函式getline(istream &in,string &s);用於從輸入流in中讀取字串到s中,以換行符’\n’分開
string類的賦值
string &operator=(const string &s);//把字串s賦給當前字串
string &assign(const char *s);//用c型別字串s賦值
string &assign(const char *s,int n);//用c字串s開始的n個字元賦值
string &assign(const string &s);//把字串s賦給當前字串
string &assign(int n,char c);//用n個字元c賦值給當前字串
string &assign(const string &s,int start,int n);//把字串s中從start開始的n個字元賦給當前字串
string &assign(const_iterator first,const_itertor last);//把first和last迭代器之間的部分賦給字串
string類的連線
string &operator+=(const string &s);//把字串s連線到當前字串的結尾
string &append(const char *s); //把c型別字串s連線到當前字串結尾
string &append(const char *s,int n);//把c型別字串s的前n個字元連線到當前字串結尾
string &append(const string &s); //同operator+=()
string &append(const string &s,int pos,int n);//把字串s中從pos開始的n個字元連線到當前字串的結尾
string &append(int n,char c); //在當前字串結尾新增n個字元c
string &append(const_iterator first,const_iterator last);//把迭代器first和last之間的部分連線到當前字串的結尾
string類的比較
bool operator==(const string &s1,const string &s2)const;//比較兩個字串是否相等
運算子">","<",">=","<=","!="均被過載用於字串的比較;
int compare(const string &s) const;//比較當前字串和s的大小
int compare(int pos, int n,const string &s)const;//比較當前字串從pos開始的n個字元組成的字串與s的大小
int compare(int pos, int n,const string &s,int pos2,int n2)const;//比較當前字串從pos開始的n個字元組成的字串與s中pos2開始的n2個字元組成的字串的大小
int compare(const char *s) const;
int compare(int pos, int n,const char *s) const;
int compare(int pos, int n,const char *s, int pos2) const;
compare函式在>時返回1,<時返回-1,==時返回0
string類的子串
string substr(int pos = 0,int n = npos) const;//返回pos開始的n個字元組成的字串
string類的交換
void swap(string &s2); //交換當前字串與s2的值
string類的查詢函式
int find(char c, int pos = 0) const;//從pos開始查詢字元c在當前字串的位置
int find(const char *s, int pos = 0) const;//從pos開始查詢字串s在當前串中的位置
int find(const char *s, int pos, int n) const;//從pos開始查詢字串s中前n個字元在當前串中的位置
int find(const string &s, int pos = 0) const;//從pos開始查詢字串s在當前串中的位置
//查詢成功時返回所在位置,失敗返回string::npos的值
int rfind(char c, int pos = npos) const;//從pos開始從後向前查詢字元c在當前串中的位置
int rfind(const char *s, int pos = npos) const;
int rfind(const char *s, int pos, int n = npos) const;
int rfind(const string &s,int pos = npos) const;
//從pos開始從後向前查詢字串s中前n個字元組成的字串在當前串中的位置,成功返回所在位置,失敗時返回string::npos的值
int find_first_of(char c, int pos = 0) const;//從pos開始查詢字元c第一次出現的位置
int find_first_of(const char *s, int pos = 0) const;
int find_first_of(const char *s, int pos, int n) const;
int find_first_of(const string &s,int pos = 0) const;
//從pos開始查詢當前串中第一個在s的前n個字元組成的數組裡的字元的位置。查詢失敗返回string::npos
int find_first_not_of(char c, int pos = 0) const;
int find_first_not_of(const char *s, int pos = 0) const;
int find_first_not_of(const char *s, int pos,int n) const;
int find_first_not_of(const string &s,int pos = 0) const;
//從當前串中查詢第一個不在串s中的字元出現的位置,失敗返回string::npos
int find_last_of(char c, int pos = npos) const;
int find_last_of(const char *s, int pos = npos) const;
int find_last_of(const char *s, int pos, int n = npos) const;
int find_last_of(const string &s,int pos = npos) const;
int find_last_not_of(char c, int pos = npos) const;
int find_last_not_of(const char *s, int pos = npos) const;
int find_last_not_of(const char *s, int pos, int n) const;
int find_last_not_of(const string &s,int pos = npos) const;
//find_last_of和find_last_not_of與find_first_of和find_first_not_of相似,只不過是從後向前查詢
string類的替換函式
string &replace(int p0, int n0,const char *s);//刪除從p0開始的n0個字元,然後在p0處插入串s
string &replace(int p0, int n0,const char *s, int n);//刪除p0開始的n0個字元,然後在p0處插入字串s的前n個字元
string &replace(int p0, int n0,const string &s);//刪除從p0開始的n0個字元,然後在p0處插入串s
string &replace(int p0, int n0,const string &s, int pos, int n);//刪除p0開始的n0個字元,然後在p0處插入串s中從pos開始的n個字元
string &replace(int p0, int n0,int n, char c);//刪除p0開始的n0個字元,然後在p0處插入n個字元c
string &replace(iterator first0, iterator last0,const char *s);//把[first0,last0)之間的部分替換為字串s
string &replace(iterator first0, iterator last0,const char *s, int n);//把[first0,last0)之間的部分替換為s的前n個字元
string &replace(iterator first0, iterator last0,const string &s);//把[first0,last0)之間的部分替換為串s
string &replace(iterator first0, iterator last0,int n, char c);//把[first0,last0)之間的部分替換為n個字元c
string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last);//把[first0,last0)之間的部分替換成[first,last)之間的字串
string類的插入函式
string &insert(int p0, const char *s);
string &insert(int p0, const char *s, int n);
string &insert(int p0,const string &s);
string &insert(int p0,const string &s, int pos, int n);
//前4個函式在p0位置插入字串s中pos開始的前n個字元
string &insert(int p0, int n, char c);//此函式在p0處插入n個字元c
iterator insert(iterator it, char c);//在it處插入字元c,返回插入後迭代器的位置
void insert(iterator it, const_iterator first, const_iterator last);//在it處插入[first,last)之間的字元
void insert(iterator it, int n, char c);//在it處插入n個字元c
string類的刪除函式
iterator erase(iterator first, iterator last);//刪除[first,last)之間的所有字元,返回刪除後迭代器的位置
iterator erase(iterator it);//刪除it指向的字元,返回刪除後迭代器的位置
string &erase(int pos = 0, int n = npos);//刪除pos開始的n個字元,返回修改後的字串
string類的迭代器處理
string類提供了向前和向後遍歷的迭代器iterator,迭代器提供了訪問各個字元的語法,類似於指標操作,迭代器不檢查範圍。
用string::iterator或string::const_iterator宣告迭代器變數,const_iterator不允許改變迭代的內容。常用迭代器函式有:
const_iterator begin()const;
iterator begin(); //返回string的起始位置
const_iterator end()const;
iterator end(); //返回string的最後一個字元後面的位置
const_iterator rbegin()const;
iterator rbegin(); //返回string的最後一個字元的位置
const_iterator rend()const;
iterator rend(); //返回string第一個字元位置的前面
rbegin和rend用於從後向前的迭代訪問,通過設定迭代器string::reverse_iterator,string::const_reverse_iterator實現

vector類:STL容器–替代陣列的使用
vector vt;
vt.reserve(100);
型別轉換:
C語言的隱式轉換和顯示轉換
C++的型別轉換運算子
static_cast(expr):類似於C語言的強制轉化,保證程式碼的安全性和正確性
可用於:相關型別轉換;例如整型、實型
子類轉父類
void *指標與其他型別指標之間的轉換
不可用於:指標之間型別的轉換
const_cast(expr):去除指標和引用的const屬性;
使用該運算子轉換意味著程式碼設計存在缺陷
dynamic_cast(expr):執行時型別識別和檢查,用於父類子類之間的轉換
reinterpret_cast(expr) :編譯的過程中進行型別轉換
reinterpret重新解釋:處理無關型別的轉換
特點:不安全,既不在編譯器期也不在執行期進行檢查,安
全性完全由程式設計師決定