主頁 > 後端開發 > C++ 入門

C++ 入門

2023-05-12 07:21:48 後端開發

001 c++ 如何作業

  • 任何以 # 開頭的陳述句,都是預處理陳述句,所謂的預處理陳述句,在編譯之前,就已經被處理了

  • 關鍵字 include:找到 <> 檔案(通常稱為“頭檔案”),然后將 <> 中的所有內容拷貝到現在的檔案里

  • main()比較特殊,雖然它的回傳值型別是 int,但它不一定需要回傳值,如果不設定回傳值,默認回傳 0

  • << 運算子叫做多載運算子,可以看成是一個函式(多載運算子 == 函式

  • 解決方案平臺(Solution Platforms):編譯代碼的目標平臺;
    x86:目標平臺是 windows32 位(生成 32 位的 windows 應用程式)

  • 預處理后,我們的檔案將被編譯,編譯器將所有 c++ 代碼 -> 二進制的機器碼

  • 源檔案.cpp --編譯--> 目標檔案.obj --鏈接--> 可執行檔案.exe

  • 鏈接:將 .obj 檔案鏈接(合并)到一起,編成一個可執行檔案,比如函式宣告,是不同.cpp之間的合并,這里強調一下,只有函式呼叫的時候,才會產生鏈接,宣告的時候,是不會進行鏈接的,宣告只是在函式被呼叫的時候,能夠找到合適的鏈接函式

  • 頭檔案不會被編譯,頭檔案拷貝過來時,已經被編譯過了;
    編譯一個單獨的檔案時,不會 link,單個檔案編譯快捷鍵:ctrl + F7

Main.cpp

#include <iostream>  # 這一條陳述句其實包含了 50623 行代碼,所以 Main.cpp 檔案才會很大

void Log(const char* message);

int main()
{
	// std::cout << "Hello World!" << std::endl;  // 將字串 Hello World! 推送到 cout 流中,然后列印到終端;endl 告訴終端,跳到下一行
        Log("Hello World!!");
	std::cin.get();  // 程式暫停執行,直到按下 enter 鍵
}

Log.cpp

#include <iostream>

void Log(const char* message)
{
	std::cout << message << std::endl;
}




002 c++ 編譯器如何作業

  • 編譯器本質作業:將我們的文本檔案 -> 目標檔案,便于后續的鏈接

  • 我們先按照編程語言的規則,將代碼進行記號化和決議成編譯能理解和推理的格式,然后編譯器對所有的代碼進行預處理,這兒會產生抽象語法樹,編譯器的作業就是將我們的代碼轉換成常量資料或指令,一旦編譯器生成這個 AST ,它可以生成實際的機器碼

  • 抽象語法樹(abstract syntax code,AST)是源代碼的抽象語法結構的樹狀表示,樹上的每個節點都表示源代碼中的一種結構,這所以說是抽象的,是因為抽象語法樹并不會表示出真實語法出現的每一個細節,比如,嵌套括號被隱含在樹的結構中,并沒有以節點的形式呈現

  • 編譯器只會編譯 .cpp 的 c++ 檔案,這些 cpp 檔案被稱為翻譯單元(一個 CPP 檔案不一定等于一個翻譯單元,如果專案較小,那么每個 CPP 檔案都是一個翻譯單元)

  • 實際上,沒有所謂的檔案,編譯器根本不 care 檔案不檔案,檔案只是提供給編譯器源代碼的一種方式而已

  • 下面的例子,主要想說明的就是,編譯器在處理頭檔案時,會把頭檔案中的所有內容都復制到當前檔案

  • 強調一下,我們平時在寫代碼的時候,要盡可能的簡潔,盡可能的優化我們的代碼,比如將 Math.cpp 中的 int result = a * b; 一行去掉,直接 return a * b; 編譯在作業時,會節省四行代碼

Math.cpp

int Math(int a, int b)
{
	int result = a * b;
	return result;
#include "EndBrace.h"

EndBrace.h

}




003 c++ 聯結器如何作業

  • 鏈接的主要作業:找到每個符合和函式在哪,并把他們鏈接起來

  • 源檔案被編譯之后,每個檔案都是單獨的翻譯單元,他們之間沒有任何關系,不能互動

  • 下面的例子很好的說明了鏈接的作用,Multiply() 定義了,即使你在當前的翻譯單元里沒有呼叫 Multiply(),但是聯結器會認為你在其他的檔案里會用到這個函式,所以,它還是會被進行鏈接,函式內部的函式呼叫,也會進行鏈接,所以呼叫的 Log() 和 Log.cpp 檔案中的 Logr() 不對應,就會產生鏈接錯誤

  • 我們可以使用 static 函式,直接規定死,Multiply() 只在當前檔案下使用,不讓它和其他變數或函式進行鏈接,就會避免上述錯誤

Math.cpp

# include <iostream>

void Log(const char* message);

// static int Multiply(int a, int b)
int Multiply(int a, int b)
{
	Log("Multiply");
	return a * b;
}

int main()
{
	std::cin.get();
}

Log.cpp

#include <iostream>

void Logr(const char* message)
{
	std::cout << message << std::endl;
}
  • 下面介紹一下,函式定義重復,導致的鏈接錯誤

  • 這里其實會報錯的,Math.cpp 和 Log.cpp 都包含了頭檔案 # include "Log.h",也就是說,Log() 的定義被復制了兩遍,產生重復鏈接錯誤,如果我們將 Log() 的修飾符改為 static 或 inline ,則會消除鏈接錯誤

  • 還有一種解決辦法就是,在 Log.h 中只宣告 Log(),然后在 Log.cpp 中定義 Log(),這樣也不會產生鏈接錯誤

Log.h

# include <iostream>

void Log(const char* message)
{
	std::cout << message << std::endl;
}

Log.cpp

# include "Log.h"

void InitLog()
{
	Log("Initialized Log");
}

Math.cpp

# include <iostream>
# include "Log.h"

static int Multiply(int a, int b)
{
	Log("Multiply");
	return a * b;
}

int main()
{
	std::cout << Multiply(5, 8) << std::endl;
	std::cin.get();
}
  • inline 的作用就是獲取實際的函式體,并將函式呼叫替換為函式體,比如在 Log.cpp
# include "Log.h"

void InitLog()
{
	// Log("Initialized Log");
        std::cout << "Initialized Log" << std::endl;
}




004 變數和函式

  • 當我們創建一個變數的時候,他們會被放到記憶體(堆和堆疊)

  • 不同變數型別之間的唯一區別:在記憶體中所占大小,而不同型別的變數所占記憶體大小與編譯器有關

  • int 資料型別可以存盤 -20億 ~ +20 億之間(約數)的值

  • 變數的型別大小與它能存盤多大的數字直接相關

  • unsigned 資料型別取值范圍 0 ~ 40 億,是因為它把符號位移除了

# include <iostream>

int main()
{
        float variable = 4.4f;  // 在值的后面添加 f 區分 float 和 double 
        double var = 9.9;
	std::cout << variable << std::endl;
	std::cout << var << std::endl;
	std::cin.get();
}
  • bool 資料型別的取值為 true 或 false,其在計算機中表示為 1 或 0,但是該型別的變數在記憶體中,占 1Byte ,雖然其只是 0 或 1,只用 1bit 就行,但是在處理尋址記憶體時,不能尋址只有 1bit 位的內容,只能尋址位元組

  • 可以使用 sizeof() 查看變數所占記憶體

Main.cpp

# include <iostream>

int main()
{
        bool var = false;
	std::cout << sizeof(var) << std::endl;  // 1
	std::cin.get();
}
  • 函式,不是 c++ 類里的

  • main() 是一個特殊的函式,可以不寫函式函式回傳值,但是其他的所有函式,都需要寫回傳值,否則會報錯

  • 函式宣告通常存盤在頭檔案中,在翻譯單元或 cpp 檔案實作定義





004 c++ 頭檔案

  • 對于 c++ 而言,頭檔案通常用于宣告某些型別的函式

  • 函式完美地解決了重復代碼的問題,而頭檔案完美解決了函式呼叫必須有宣告的問題,有了頭檔案,就不用在每個翻譯單元宣告函式了

  • 如果我們在 .h 頭檔案里包含了 #include 那么在翻譯單元里,只要包含了 .h 檔案,不添加 #include 也可以

  • pragma 是一個被發送到編譯器或前處理器的預處理指令

  • pragma once 監督頭檔案,阻止單個頭檔案多次被包含

Log.h

# pragma once  // 只包括這個頭檔案一次
  • 如果我們要包含的檔案,在其中的一個檔案夾里,用尖括號 <> 告訴編譯器,搜索包含路徑檔案夾,說白了就是,用引號可以指定相對路徑

  • 而引號 "" 通常是告訴編譯器,包含相對于當前檔案的檔案

  • c++ 標準庫,通常沒有后綴 .h,是為了和 c 進行區分

  • 在 vs 里,可以右鍵打開檔案,查看所選頭檔案完整內容;右鍵函式名,可以查看函式定義

持續更新ing....

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/552176.html

標籤:C++

上一篇:在 IDEA 中創建 Spring Boot 專案的方式(詳細步驟教程)

下一篇:返回列表

標籤雲
其他(158833) Python(38125) JavaScript(25413) Java(18025) C(15225) 區塊鏈(8264) C#(7972) AI(7469) 爪哇(7425) MySQL(7177) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5871) 数组(5741) R(5409) Linux(5338) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4570) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1972) 功能(1967) Web開發(1951) HtmlCss(1935) python-3.x(1918) C++(1914) 弹簧靴(1913) xml(1889) PostgreSQL(1875) .NETCore(1860) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • C++ 入門

    001 c++ 如何作業 任何以 # 開頭的陳述句,都是預處理陳述句,所謂的預處理陳述句,在編譯之前,就已經被處理了 關鍵字 include:找到 <> 檔案(通常稱為“頭檔案”),然后將 <> 中的所有內容拷貝到現在的檔案里 main()比較特殊,雖然它的回傳值型別是 int,但它不一定需要回傳值,如果 ......

    uj5u.com 2023-05-12 07:21:48 more
  • 在 IDEA 中創建 Spring Boot 專案的方式(詳細步驟教程)

    開發環境 以下是我的開發環境 JDK 1.8 Maven 3.6.3 IDEA 2019(2019 無所畏懼,即使現在已經 2023 年了哈哈哈) 使用 Maven 的方式創建 Spring Boot 專案 下面的內容可能會因 IDEA 版本不同,而有些選項不同,但是大同小異。 1. 打開 IDEA ......

    uj5u.com 2023-05-11 07:32:53 more
  • Java for回圈標簽跳轉到指定位置

    大家是否見過這種for回圈,在for回圈前加了個標記的: outerLoop: for (; ; ) { for (; ; ) { break outerLoop; } } 我之前有一次在公司業務代碼中見過有這種寫法的,沒在意,今天在看JDK執行緒池的代碼時,又看到ThreadPoolExecutor ......

    uj5u.com 2023-05-11 07:32:35 more
  • 訊息推送平臺的實時數倉?!flink消費kafka訊息入到hive

    大家好,3y啊。好些天沒更新了,并沒有偷懶,只不過一直在安裝環境,差點都想放棄了。 上一次比較大的更新是做了austin的預覽地址,把企業微信的應用和機器人訊息各種的訊息型別和功能給完善了。上一篇文章也提到了,austin常規的功能已經更新得差不多了,剩下的就是各種細節的完善。 不知道大家還記不記得 ......

    uj5u.com 2023-05-11 07:32:30 more
  • Hibernate 基本操作、懶加載以及快取

    上一篇咱們介紹了 Hibernate 以及寫了一個 Hibernate 的工具類,快速入門體驗了一波 Hibernate 的使用,我們只需通過 Session 物件就能實作資料庫的操作了。

    現在,這篇介紹使用 Hibernate 進行基本的 CRUD、懶加載以及快取的知識。 ......

    uj5u.com 2023-05-11 07:32:24 more
  • 【Visual Leak Detector】核心原始碼剖析(VLD 2.5.1)

    使用 VLD 記憶體泄漏檢測工具輔助開發時整理的學習筆記。本篇對 VLD 2.5.1 原始碼做記憶體泄漏檢測的思路進行剖析。 ......

    uj5u.com 2023-05-11 07:32:18 more
  • 34基于Java的學生選課系統或學生課程管理系統

    基于java的學生課程管理系統,基于java的學生選課系統,javaWeb的學生選課系統,學生成績管理系統,課表管理系統,學院管理系統,大學生選課系統設計與實作,網上選課系統,課程成績打分。 ......

    uj5u.com 2023-05-11 07:32:13 more
  • 最佳實踐:路徑路由匹配規則的設計與實作

    本文設計并實作了一種專用于路徑路由匹配的規則,以一種簡單而通用的方式描述一組路徑的特征,來簡化這種場景路由描述難度,讓小白可以快速學習并上手。 ......

    uj5u.com 2023-05-11 07:25:44 more
  • 文盤Rust —— rust連接oss | 京東云技術團隊

    物件存盤是云的基礎組件之一,各大云廠商都有相關產品。這里跟大家介紹一下rust與物件存盤交到的基本套路和其中的一些技巧。 ......

    uj5u.com 2023-05-10 10:44:00 more
  • Java的抽象類 & 介面

    抽象類:在子類繼承父類時,父類的一些方法實作是不明確的(父類對子類的實作一無所知)。這時需要使父類是抽象類,在子類中提供方法的實作。

    介面(interface)技術主要用來描述類具有什么功能,而并不給出每個功能的具體實作。 ......

    uj5u.com 2023-05-10 10:38:48 more