Modern C++(一)基本概念

1、基本概念

1.1、注釋

注釋在翻譯階段3會被替換為單個空白字符從程序中移除

1.2、名字與標識符

標識符是一個由數字、下劃線、大小寫字符組成的任意長度序列。有效的標識符首個字符必須是以A-Z、a-z、下劃線開頭,。有效的標識符其他字符可以是0-9、A-Z、a-z、下劃線。

標識符可以用來命名對象、引用、函數、枚舉項、類型、類成員、命名空間、模板、模板特化、形參包(C++11 起)、goto 標號,以及其他實體。

1.3、類型

C++類型系統由以下類型組成:

  • 基礎類型
    • void
    • std::nullptr_t
    • 算數類型
      • bool
      • 字符類型:char、signed char、unsigned char、char16_t、char32_t、wchar_t
      • 有符號整數類型:signed char、short int、int、long int、long long int
      • 無符號整數類型:
      • 浮點數類型:float、double、long double
  • 復合類型
    • 引用類型:
      • 左值引用類型
      • 右值引用類型
      • 指針類型
      • 指向成員的指針(成員指針)類型
      • 數組類型
      • 函數類型
      • 枚舉類型(有/無作用域)
      • 類類型(非聯合/聯合體類型)

標量類型:標量類型變量一次僅存儲一個值。算術類型、枚舉類型、指針類型、成員指針類型、std::nullptr_t都是標量類型

1.3.1、隱式生存期類型

隱式生存期類型是C++20引入的概念,無需顯式調用構造函數或使用new表達式,對象的生存期(lifetime)可以隱式開始。

普通生存期類型:

class Person {
public:Person(const std::string& name) : name_(name) {std::cout << "構造: " << name_.c_str() << std::endl;}~Person() {std::cout << "析構: " << name_.c_str() << std::endl;}std::string name_;
};int main()
{void *mem = malloc(sizeof(Person));// 未定義行為!必須先構造再使用// static_cast<Person*>(mem)->name_ = "Alice";Person* p = new (mem) Person("Alice");  // 調用構造函數p->~Person();  // 顯式調用析構函數std::free(mem);  // 釋放內存
}

隱式生存期類型:

struct Point {int x;int y;
};int main()
{void* memory = std::malloc(sizeof(Point));  // 分配內存// 可以直接使用,無需構造!Point* p = static_cast<Point*>(memory);p->x = 10;  // 合法:內存已被視為Point對象p->y = 20;free(memory); // 釋放內存(自動析構,無需顯式調用析構函數)
}

隱式生存期類型允許:直接操作未構造的內存,無需顯式銷毀對象,可直接覆蓋內存。優點是預先分配大塊內存(內存池),按需創建對象。避免頻繁調用構造 / 析構函數,提升內存操作效率。

隱式生存期類型:

  • 標量類型
  • 結構體 / 類需滿足:無用戶定義的構造函數、析構函數。所有成員和基類都是隱式生存期類型。

1.3.2、靜態類型

靜態類型(Static Typing)是一種編程語言特性,它要求在編譯時明確每個變量、表達式和函數的類型。

1.3.3、動態類型

動態類型(Dynamic Typing)是一個相對概念,主要指程序在運行時確定對象的實際類型,而非編譯時。C++ 作為靜態類型語言,其核心類型系統是靜態的(編譯時確定類型),有以下幾個機制提供了有限的動態類型特性:

  • 多態:基類指針指向派生類對象
  • RTTI(運行時類型信息)

1.4、對象

1.4.1、對齊

每個對象類型都具有被稱為對齊要求的性質,它是一個非負整數(類型是 std::size_t,總是 2 的冪),可以使用alignof和std::alignment_of查詢類型的對齊要求,也可以使用alignas要求對齊數。

class Person {
public:Person(const std::string& name) : name_(name) {}
private:std::string name_;
};int main()
{cout << alignof(Person) << endl;cout << std::alignment_of<Person>::value << endl;
}

1.4.2、聲明點

聲明點(Point of Declaration)是一個編譯期概念,它指定了標識符(如變量、函數、類等)在代碼中正式生效的位置。

  • 對于變量和函數參數:聲明點位于標識符名稱之后,初始化表達式(如果有)之前
#include <iostream>int main(int argc, char **argv) {int x = 1;const int y = 2;{int x = x;      // 內部x的作用域在初始化器之前就開始了,所以內部x不能被外部x的值初始化std::cout << "x = " << x << std::endl;int y[y] = {};    // 內部y的作用域在y[y]之后,所以內部的y是一個包含2個int的數組}return 0;
}
  • 類和類模板,枚舉的聲明點位于該標識符之后:
struct S : public A{ // S 的作用域從冒號開始}enum E : int // E 的作用域從冒號開始,因此內部可以使用枚舉類型E
{A = sizeof(E)
};
  • 類型別名或別名模板聲明的聲明點緊隨該別名代表的類型標識之后
using T = int; // 外部 T 的作用域從分號開始
{using T = T*; // 內部 T 的作用域從分號開始,// 但分號前還在外部 T 的作用域中,// 因此等同于 T = int*
}
  • 對于函數:聲明點位于函數名稱之后,形參列表之前
void func(int x) {  // func的聲明點在此處// 函數體中可使用func(如遞歸調用)
}

1.4.3、生存期

對象的生存期(Lifetime) 是指對象從創建(存儲被分配且初始化完成)到銷毀(存儲被釋放或重用)的時間段。理解對象生存期對于避免內存泄漏、懸空指針和資源管理至關重要。

生存期:當對象獲取存儲并初始化完成后生存期開始。對象的生存期在以下幾個時刻結束:

  • 非類類型:銷毀該對象時
  • 類類型:析構函數調用開始時
  • 對象占據的存儲被釋放,或者被其他對象重用
#include <iostream>class A {
public:A() {a = 10;}~A(){}void print() {std::cout << "A: a = "<< a << std::endl;}int a;
};class B {
public:int c;B() {c = 1;}
};void func() {A a;a.~A();new (&a) B;a.print();
}int main(int argc, char **argv) {func();std::cout << "test" << std::endl;return 0;
}

在上述代碼func函數里,我們手動調用了a的析構函數,對象a的生命周期結束了,該對象占用的存儲還在,但它已經不再是一個有效的對象,后續的print調用實際上時一個未定義的行為。

棧上的內存回收是由操作系統自動完成的,當對象的生命周期結束時,操作系統并不會立即將該對象所占用的內存標記為可用,而是等到整個棧幀(通常對應一個函數調用)結束時才會回收棧上的內存。因此,在對象的生命周期結束后,其所在的內存仍然存在,只是該內存已經不再屬于一個有效的對象。

所以析構函數調用后,我們還可以重用a的內存。

生存期分類:

  • 自動生存期:局部變量(非static),從定義處開始,到離開作用域時結束。
  • 靜態生存期:全局變量、static局部變量、static成員,從程序啟動開始,到程序結束結束。
  • 動態生存期:通過new/new[]分配的對象,從new成功開始,到delete/delete[]結束。
  • 線程局部生存期:thread_local變量,與線程綁定(線程啟動時開始,線程結束時結束)。

訪問生存期外的對象 或者 重用存儲前未結束生存期會導致未定義行為(UB)。

int* p = new int(10);
delete p;
*p = 20; // UB:p指向的對象已銷毀struct S { ~S() {} };
S* s = new S;
new (s) S; // UB:原S的生存期未顯式結束(需先調用析構)

1.5、聲明與定義

聲明(Declaration) 和 定義(Definition) 是兩個核心概念,它們的區別直接影響代碼的編譯和鏈接過程。

1.5.1、聲明

聲明的主要作用是向編譯器介紹某個標識符(如變量、函數、類等)的存在,告知編譯器該標識符的名稱、類型和一些基本屬性,但并不為其分配內存或實現具體的功能。

聲明的用途是解決編譯時的符號引用。

以下情況是聲明

  • 變量聲明:用extern關鍵字且不帶初始化器
extern const int a;
  • 類定義中的非 inline(C++17 起) 靜態數據成員的聲明
struct S
{int n;               // 定義 S::nstatic int i;        // 聲明 S::iinline static int x; // 定義 S::x
};                       // 定義 S
int S::i;                // 定義 S::i
  • 函數聲明:僅提供簽名
void foo(int a);
  • 類/類型聲明:
class MyClass;
enum Color : int;
  • typedef 聲明,using 聲明
typedef S S2;   // 聲明但不定義 S2(S 可以是不完整類型)
using S2 = S;   // 聲明但不定義 S2(S 可以是不完整類型)
using N::d;     // 聲明,引入一個已存在的名稱,所以N::d必須已經被聲明

重要:聲明可多次重復(同一作用域內允許多次聲明),但是聲明必須完全一致

extern int x;     // 聲明1
extern double x;  // 錯誤:類型不一致

函數聲明可能分散在多個頭文件中,最終在源文件中定義

// utils.h
void helper();// math.h
void helper(); // 重復聲明(合法)// utils.cpp
void helper() {} // 唯一定義

1.5.2、定義

定義是為標識符分配存儲空間或提供完整實現。每個標識符必須有且僅有一個定義(One Definition Rule, ODR)。

定義的用途是解決鏈接時的具體實現。

  • 變量定義:
int x = 42; // 定義并初始化x(分配內存)
  • 函數定義
void foo(int a) { // 函數定義std::cout << a;
}
  • 類定義:完整描述成員和方法。
class MyClass {
public:void method() {}
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905639.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905639.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905639.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32的TIMx中Prescaler和ClockDivision的區別

Prescaler預分頻&#xff0c;以筆者目前的學習程度來說&#xff0c;這個參數&#xff0c;一般來說是對主時鐘進行分頻后的計數器時鐘。這個預分頻后的時鐘主要是用于的計數的。 這個主時鐘&#xff0c;對于時基單元來說可以是內部時鐘&#xff0c;也可以是外部時鐘。一般來說我…

前端性能指標及優化策略——從加載、渲染和交互階段分別解讀詳解并以Webpack+Vue項目為例進行解讀

按照加載階段、渲染階段和交互階段三個維度進行系統性闡述&#xff1a; 在現代 Web 開發中&#xff0c;性能不再是錦上添花&#xff0c;而是決定用戶體驗與業務成敗的關鍵因素。為了全面監控與優化網頁性能&#xff0c;我們可以將性能指標劃分為加載階段、渲染階段、和交互階段…

MySQL——1、數據庫基礎

數據庫基礎 1、安裝MySQL2、什么是數據庫3、數據庫使用案例4、MySQL架構與SQL分類5、存儲引擎 1、安裝MySQL 1、更新軟件包列表 sudo apt update2、查看MySQL安裝包 apt list | grep mysql-server3、安裝MySQL # 默認安裝最新版 sudo apt install -y mysql-server4、啟動My…

ET MailBoxComponent類(實體) 分析

MailBoxComponent 作用是&#xff0c;用來接收Actor消息&#xff0c;處理Actor消息。這個沒有存儲能&#xff0c;收到消息后立即就處理了。ParentInstanceId 是MailBox所在的實體InstanceIdMailBoxType MailBox類型MailBoxInvoker 分發消息的包裝Add 方法&#xff0c;看名字是…

Weblogic SSRF漏洞復現(CVE-2014-4210)【vulhub靶場】

漏洞概述&#xff1a; Weblogic中存在一個SSRF漏洞&#xff0c;利用該漏洞可以發送任意HTTP請求&#xff0c;進而攻擊內網中redis、fastcgi等脆弱組件。 漏洞形成原因&#xff1a; WebLogic Server 的 UDDI 組件&#xff08;uddiexplorer.war&#xff09;中的 SearchPublicR…

js應用opencv

思路&#xff1a; 第一步&#xff1a;直方圖 第二步&#xff1a;獲得直方圖的波峰 第三步&#xff1a;波峰勝負10&#xff0c;高于或低于變紅色 1.引用import cv from ‘techstark/opencv-js’; 2.vue代碼 <div class"historyLeft2"><div style"relat…

用Python代碼繪制動態3D愛心效果

引言 介紹Python在創意編程中的應用&#xff0c;特別是如何通過簡單的代碼實現視覺上的美感。引出本文將分享的愛心代碼&#xff0c;并簡要說明其實現原理。 愛心代碼的基本實現 展示一個簡單的Python代碼示例&#xff0c;使用字符畫的方式在控制臺中繪制一個愛心圖案。 pr…

使用Python開發經典俄羅斯方塊游戲

使用Python開發經典俄羅斯方塊游戲 在這篇教程中&#xff0c;我們將學習如何使用Python和Pygame庫開發一個經典的俄羅斯方塊游戲。這個項目將幫助你理解游戲開發的基本概念&#xff0c;包括圖形界面、用戶輸入處理、碰撞檢測等重要內容。 項目概述 我們將實現以下功能&…

兼顧長、短視頻任務的無人機具身理解!AirVista-II:面向動態場景語義理解的無人機具身智能體系統

作者&#xff1a;Fei Lin 1 ^{1} 1, Yonglin Tian 2 ^{2} 2, Tengchao Zhang 1 ^{1} 1, Jun Huang 1 ^{1} 1, Sangtian Guan 1 ^{1} 1, and Fei-Yue Wang 2 , 1 ^{2,1} 2,1單位&#xff1a; 1 ^{1} 1澳門科技大學創新工程學院工程科學系&#xff0c; 2 ^{2} 2中科院自動化研究所…

【藍橋杯省賽真題49】python偶數 第十五屆藍橋杯青少組Python編程省賽真題解析

python偶數 第十五屆藍橋杯青少組python比賽省賽真題詳細解析 博主推薦 所有考級比賽學習相關資料合集【推薦收藏】1、Python比賽 信息素養大賽Python編程挑戰賽 藍橋杯python選拔賽真題詳解

鴻蒙(HarmonyOS)應用開發入門教程

目錄 第一章:鴻蒙系統簡介 1.1 什么是鴻蒙系統? 1.2 鴻蒙系統架構 第二章:開發環境搭建 2.1 安裝DevEco Studio 步驟1:下載與安裝 步驟2:首次配置 步驟3:設備準備 2.2 創建第一個項目 第三章:鴻蒙應用開發基礎 3.1 核心概念:Ability與AbilitySlice 示例代碼…

VM中 ubuntu 網卡不顯示

1.添加網卡配置 #sudo nano /etc/netplan/01-netcfg.yaml network:version: 2renderer: networkdethernets:ens33:dhcp4: trueens37:dhcp4: trueens38:dhcp4: true#保存后 sudo netplan apply2.查看網絡狀態 sudo systemctl start systemd-networkd sudo systemctl status sy…

阿克曼-幻宇機器人系列教程3- 機器人交互實踐(Message)

上一篇文章介紹了如何通過topic操作命令實現與機器人的交互&#xff0c;本篇我們介紹如何通過Message&#xff08;即topic的下一級&#xff09;實現與機器人的交互。 和topic一樣&#xff0c;首先在一個終端通過ssh命令登錄機器人、啟動機器人&#xff0c;然后打開另外一個終端…

Python 調試擴展版本兼容問題解決紀實

在 Python 開發中&#xff0c;調試工具的正常使用對效率至關重要。近期在公司項目中&#xff0c;便遇到了 Python 調試擴展與版本不兼容的問題。公司 ERP 服務器采用 Ubuntu 18.04 系統&#xff0c;其標配 Python 版本為 3.6&#xff0c;而常用的 Python Debugger 擴展對版本有…

React 第四十二節 Router 中useLoaderData的用途詳解

一、前言 useLoaderData&#xff0c;用于在組件中獲取路由預加載的數據。它通常與路由配置中的 loader 函數配合使用&#xff0c;用于在頁面渲染前異步獲取數據&#xff08;如 API 請求&#xff09;&#xff0c;并將數據直接注入組件&#xff0c;從而簡化數據流管理。 二、us…

Linux——mysql主從復制與讀寫分離

目錄 一&#xff0c;理解什么是mysql主從復制 1&#xff0c;mysql支持的復制類型 2&#xff0c;mysql主從復制的工作流程 二&#xff0c;配置mysql主從復制 三&#xff0c;配置mysql主主復制 四&#xff0c;mysql讀寫分離 1&#xff0c;了解什么是mysql讀寫分離 2&…

MongoDB數據庫深度解析:架構、特性與應用場景

在現代應用程序開發中&#xff0c;數據存儲技術的選擇至關重要。在眾多的數據庫管理系統中&#xff0c;MongoDB以其靈活性和強大的功能迅速崛起&#xff0c;成為NoSQL數據庫中的佼佼者。本文將深入解析MongoDB的架構、核心特性、性能優化及其在實際應用中的最佳實踐&#xff0c…

3D曲面上的TSP問題(一):曲面上點集距離求解

3D曲面上&#xff0c;兩點的距離求解不能采用歐式距離&#xff0c;而需要計算測地線距離。 代碼使用CGAL 5.6.2 OpenCV 4.11.0 版本實現 #include "cgal_utils.h" #include <CGAL/AABB_tree.h> #include <CGAL/AABB_traits.h> #include <CGAL/AABB_…

【歌曲結構】2:小節與歌曲結構信息整合

歌曲小節與結構信息整合 我將為您整合小節信息與歌曲結構,創建一個更加詳細的JSON數據結構。 處理方法 將小節時間與歌曲結構段落進行匹配為每個小節添加所屬段落信息為小節添加格式化的時間戳為小節添加對應時間范圍內的歌詞{"song_title": "財神廟前許三億…

C語言:深入理解指針(3)

目錄 一、數組名的理解 二、用指針訪問數組 三、一維數組傳參的本質 四、冒泡排序 五、二級指針 六、指針數組 七、指針數組模擬二維數組 八、結語 一、數組名的理解 數組名其實就是首元素的地址 int arr[3] {1,2,3}; printf("arr :%p\n" ,arr); printf(…