C++初學者指南-3.自定義類型(第一部分)-指針

C++初學者指南-3.自定義類型(第一部分)-指針

文章目錄

  • C++初學者指南-3.自定義類型(第一部分)-指針
    • 1.為什么我們需要它們?
    • 2.T 類型的對象指針
      • 原始指針:T *
      • 智能指針(C++11)
    • 3.操作符
      • 地址操作符 &
      • 解引用運算符 *
      • 成員訪問操作符 ->
      • 語法
      • 重定向
    • 4.nullptr (C++11)
    • 5.const 和指針
    • 6. "this"指針
    • 7.前置類型聲明
    • 8. 盡量避免使用指針

1.為什么我們需要它們?

觀察對象

  • 不復制的間接引用:引用/跟蹤對象
  • 如果我們想要在運行時更改間接目標 ? 不能使用引用

訪問動態內存

  • 訪問具有動態存儲期的對象,即生命周期不與變量或作用域綁定的對象(后續章節會介紹)。

構建動態的、基于節點的數據結構
在這里插入圖片描述

2.T 類型的對象指針

  • 存儲 T 類型對象的內存地址
  • 可用于檢查/觀察/修改目標對象
  • 可以重定向到不同的目標(與引用不同)
  • 也可能指向根本沒有的對象(是 Null 指針)
    在這里插入圖片描述

原始指針:T *

  • 本質上是一個(無符號的)整數變量,用于存儲內存地址
  • 大小:64 位平臺上為64 位
  • 許多原始指針可以指向相同的地址/對象
  • 指針和目標(被指向的)對象的生命周期是獨立的

智能指針(C++11)

std::unique_pointer

  • 用于訪問動態存儲,即堆上的對象
  • 每個對象只能有一個 unique_ptr
  • 指針和目標對象具有相同的生命周期

std::shared_pointer
std::weak_pointer

  • 用于訪問動態存儲,即堆上的對象
  • 每個對象可以有多個shared_ptrs 或 weak_ptrs
  • 只要至少有一個shared_ptr指向目標對象,目標對象就會存在

我們將在后面的章節中學習如何使用這些智能指針。

3.操作符

地址操作符 &

char  c = 65;
char* p = &c;
  • T* 類型的原始指針變量可以存儲 T 類型對象的地址。
  • &c 返回 C 的內存地址
    在這里插入圖片描述

解引用運算符 *

char  c = 65;
char* p = &c;
*p = 88;
char  x = *p;
  • &c 返回 c 的內存地址
  • *p 訪問 p 中地址的值
    在這里插入圖片描述

成員訪問操作符 ->

struct Coord {char x = 0; char y = 0; 
};
Coord a {12,34};
Coord* p = &a;
char v = p->x;  // v = 12
char w = p->y;  // w = 34
// 另外的方式:
char s = (*p).x;  // s = 12
char t = (*p).y;  // t = 34

在這里插入圖片描述

語法

*&
類型修飾符指針聲明引用聲明
一元運算符解引用
value = *pointer;
取得地址
pointer = &variable;
二元運算符乘法
product = expr1 * expr2;
按位與
bitand = expr1 & expr2;

聲明陷阱

int*  p1, p2;    // int*, int
int  *p1, *p2;   // int*, int*

更好且更明確:

int* p1 = …;
int* p2 = …;

重定向

與引用不同,指針可以重定向

int a = 0;
int b = 0;            // a: 0    b: 0 
int* p = &a;          // p→a   a: 0    b: 0
*p = 2;               // p→a   a: 2    b: 0
p = &b;               // p→b   a: 2    b: 0
*p = 9;               // p→b   a: 2    b: 9
cout << a;  // 2
cout << b;  // 9

運行上面代碼

4.nullptr (C++11)

  • 特殊指針值
  • 可以隱式轉換為 false
  • 在內存中不一定用 0 表示! (取決于平臺)

編碼約定:nullptr 表示值不可用

  • 在初始化時將指針設置為 nullptr 或有效地址
  • 在解引用之前檢查是否不是 nullptr
int* p = nullptr;   // 初始化為nullptr
if (…) {                             int i = 5;p = &i;  // 分配有效地址…// 在解引用之前檢查!if (p) *p = 7;  …// 設置為nullptr,表示“不可用”。p = nullptr;   
}                             
// i的內存被釋放,任何指向i的指針都會變得無效!

5.const 和指針

目的

  1. 只讀訪問對象
  2. 防止指針重定向

語法

指向類型 T 的指針指向值可修改指針本身可修改
T *可以可以
T const *不可以可以
T * const可以不可以
T const * const不可以不可以

從右到左讀:“(const)指向(const)T的指針”
例子:

int i = 5;
int j = 8;
int const* cp = &i;
*cp = 8;   //  編譯器錯誤:指向的值是const
cp = &j;   //  OK
int *const pc = &i;
*pc = 8;   //  OK
pc = &j;   //  編譯器錯誤:指針本身是常量
int const*const cpc = &i;
*cpc = 8;  //  編譯器錯誤:指向的值是常量
cpc = &j;  //  編譯器錯誤:指針本身是常量

一個關于風格的持續辯論…

右const左const
一個一貫的規則: const 的剩余部分保持不變更普遍,但不太一致
int const c = …;
int const& cr = …;
int const* pc = …;
int *const cp = …;
int const * const cpc = …;
const int c = 1;
const int& cr = …;
const int* pc = …;
int *const cp = …;
const int *const cpc = …;

6. "this"指針

  • 成員函數內部可用
  • this 返回對象本身的地址
  • this-> 可用于訪問成員
  • *this 訪問對象本身
class IntRange {int l_ = 0;int r_ = 0;
public:explicitIntRange (int l, int r): l_{l}, r_{r} {if (l_ > r_) std::swap(l_, r_);}int left ()  const { return l_; }// can also use 'this' to access members:int right () const { return this->r_; }// returns reference to object itselfIntRange& shift (int by) {l_ += by;r_ += by;return *this;}IntRange& widen (int by) {l_ -= by;r_ += by;return *this;}
};

運行上面代碼

IntRange r1 {1,3};                  // 1 3
r1.shift(1);                        // 2 4
r1.shift(2).widen(1);               // 3 7

7.前置類型聲明

有時候如果需要讓兩種類型相互引用的話是必要的:

// 前置聲明
class Hub;
class Device {Hub* hub_;…
};
class Hub {std::vector<Device const*> devs_;…
};

在這里插入圖片描述
為了定義一個類型,必須要知道它所有成員的內存大小。

  • 這只有在完全了解所有成員的定義的情況下才可能實現。
  • 但是,所有指針類型都具有相同的大小

?我們可以:
聲明 Hub 的存在,因為 Device 只需要一個指向它的指針。

8. 盡量避免使用指針

指針容易懸空

  • 懸空 = 指向無效/無法訪問的內存地址的指針
  • 存儲在指針中的值可以是任何地址
  • 程序員必須確保指針目標有效/仍然存在
int* p;  // p 沒有初始化!
*p = 7;  //  未知行為
p = nullptr;  
*p = 7;  //  訪問空指針導致未知行為
{int x = 8;  p = &x;   
}        // x的生命周期已經結束
*p = 7;  // 訪問已經釋放的內存導致未知行為

容易出錯的參數傳遞

void swap_values (int* a, int* b) {int t = *a;*a = *b;*b = t;
}
int x = 3, y = 4;
swap_values(&x, &y)        // OK
swap_values(&x, 0);        //  未知行為
swap_values(&x, nullptr);  //  未知行為

代碼更難閱讀

*p = *p * *p + (2 * *p + 1);   // 太多星號了!

建議:如果可能,首選引用,尤其是對于函數參數

附上原文地址
如果文章對您有用,請隨手點個贊,謝謝!^_^

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

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

相關文章

【Linux】用戶管理

創建與刪除 adduser adduser 是一個交互式命令&#xff0c;用于創建新用戶并設置初始環境。 sudo adduser 用戶名示例&#xff1a; sudo adduser newuseruseradd useradd 是一個非交互式命令&#xff0c;允許你通過選項指定用戶的屬性。 sudo useradd [選項] 用戶名常見選…

SCADA系統對于工業生產的意義!

關鍵字:LP-SCADA系統, 傳感器可視化, 設備可視化, 獨立SPC系統, 智能儀表系統,SPC可視化,獨立SPC系統 SCADA系統在智能制造中扮演著至關重要的角色&#xff0c;它通過集成和自動化工廠車間的各種過程&#xff0c;提高了生產效率和產品質量&#xff0c;降低了成本&#xff0c;并…

【AI繪畫 ComfyUI】全新整合包來襲!一鍵安裝 即開即用,超好用的工作流形式的AI繪畫工具!

大家好&#xff0c;我是畫畫的小強 請在看這篇文章的人注意&#xff0c;本文章介紹的Comfy UI整合包是一個節點式的工作&#xff0c;流式的AI繪畫界面&#xff0c;并不適合新手使用。 如果你在找的是Web UI, 請前往我之前發布一篇的文章AI繪畫『Stable Diffusion』面向小白的…

【高中數學/基本不等式】設a,b>0.a+b=5,則 根號下(a+1)+根號下(b+3) 的最大值為?(2015重慶卷)

【問題】 設a,b>0.ab5,則根號下(a1)根號下(b3)的最大值為&#xff1f; 【解答】 解法一&#xff1a; 因雙根號計算不便&#xff0c;故采用平方后簡化之。 原式的平方a12倍根號下((a1)(b3))b3 ab42倍根號下((a1)(b3)) 因為ab5 a1b31359 9(a1)(b3)>2倍根號下((a1)…

【小貪】項目實戰——Zero-shot根據文字提示分割出圖片目標掩碼

目標描述 給定RGB視頻或圖片&#xff0c;目標是分割出圖像中的指定目標掩碼。我們需要復現兩個Zero-shot的開源項目&#xff0c;分別為IDEA研究院的GroundingDINO和Facebook的SAM。首先使用目標檢測方法GroundingDINO&#xff0c;輸入想檢測目標的文字提示&#xff0c;可以獲得…

uniapp中如何進行微信小程序的分包

思路&#xff1a;在uniapp中對微信小程序進行分包&#xff0c;和原生微信小程序進行分包的操作基本上沒區別&#xff0c;主要就是在pages.json中進行配置。 如圖&#xff0c;我新增了一個包diver-page 此時需要在pages.json中的subPackages數組中新增一項 root代表這個包的根…

用好華為小助手,生活總能快人一步

嘿&#xff01;朋友們&#xff01;你們有沒有想過&#xff0c;如果身邊有一個小助手&#xff0c;他不僅聰明伶俐&#xff0c;還能在生活的方方面面給予你最貼心的關懷和幫助&#xff0c;讓我們的日常生活變得更加方便和快捷&#xff0c;那該有多好&#xff01;沒錯&#xff0c;…

【云原生】Kubernetes資源配額+HPA+節點選擇器+親和性+污點

Kubernetes高級功能 文章目錄 Kubernetes高級功能一、資源配額1.1、什么是資源配額1.2、資源配額應用1.2.1、針對Namespace設置資源配額1.2.2、針對Pod設置資源配額 二、HorizontalPodAutoscaler&#xff08;HPA&#xff09;2.1、什么是HorizontalPodAutoscaler2.2、Horizontal…

談談創意設計中的AI、AGI、AIGC

在當今的數字化時代&#xff0c;創意設計領域正經歷著前所未有的變革。隨著人工智能&#xff08;AI&#xff09;、通用人工智能&#xff08;AGI&#xff09;以及人工智能生成內容&#xff08;AIGC&#xff09;的迅猛發展&#xff0c;設計師們的工作方式和創作手段都發生了深刻的…

Spring Boot中的緩存配置與優化

Spring Boot中的緩存配置與優化 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將探討在Spring Boot應用中如何配置和優化緩存&#xff0c;以提升系統的…

UML形式化建模期末復習筆記

本文檔為xmind導出&#xff0c;可能存在缺少圖片等問題&#xff0c;建議下載思維導圖查看完整內容 鏈接: https://pan.baidu.com/s/17s-utC2C6Qg0tFp61Kw0ZQ?pwduq64 提取碼: uq64 概述 UML: Unified Modeling Language 統一建模語言 建模 定義 把不太理解的東西和一些已經較…

隔離級別是如何實現的?

在數據庫管理系統中&#xff0c;隔離級別&#xff08;Isolation Level&#xff09;是用來定義事務在執行過程中可以看到其他事務執行中的操作的一個設置。這主要用于控制事務之間的并發性和數據一致性。SQL標準定義了四種隔離級別&#xff0c;每種級別都以不同的方式平衡了性能…

Swift 中的 StoreKit 測試

文章目錄 前言創建一個 StoreKit Demo使用 SKTestSessionaskToBuyEnabled 屬性總結前言 StoreKit 框架的第二次迭代是我在過去幾年中應用程序中最重大的變化。最近版本的 StoreKit 框架已完全采用了 Swift 語言特性,如 async 和 await。本篇內容我們將討論 StoreKitTest 框架…

【揭秘】嘴尚絕鹵味健康新風尚,讓你吃得美味又健康!

在快節奏的現代生活中&#xff0c;美食不僅是味蕾的享受&#xff0c;更是健康生活的追求。今天&#xff0c;我們要聊的就是備受食客們青睞的“嘴尚絕鹵味”——如何在享受美味的同時&#xff0c;也能兼顧健康飲食的理念。 一、鹵味文化&#xff0c;源遠流長 鹵味&#xff0c;作…

Redis緩存管理機制

在當今快節奏的數字世界中&#xff0c;性能優化對于提供無縫的用戶體驗至關重要。緩存在提高應用程序性能方面發揮著至關重要的作用&#xff0c;它通過將經常使用或處理的數據存儲在臨時高速存儲中來減少數據庫負載并縮短響應時間&#xff0c;從而減少系統的延遲。Redis 是一種…

navicat Lite 版

navicat Lite 版&#xff1a; Navicat 出了一個 Navicat Premium 的Lite版。 官方現在鏈接&#xff1a;https://www.navicat.com.cn/download/navicat-premium-lite#windows 從官網可以看到現在能夠下載最新版本 17&#xff0c;支持各種平臺

[vue2/vue3] 詳細剖析watch、computed、watchEffect的區別,原理解讀

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;我是前端菜鳥的自我修養&#xff01;今天給大家分享【深入剖析watch、computed、watchEffect的區別】&#xff0c;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;原創不易&#xff0c;如果能幫助到帶大家…

為什么企業應用開發,c++干不過java?

在開始前剛好我有一些資料&#xff0c;是我根據網友給的問題精心整理了一份「c的資料從專業入門到高級教程」&#xff0c; 點個關注在評論區回復“888”之后私信回復“888”&#xff0c;全部無償共享給大家&#xff01;&#xff01;&#xff01; C/C這種東西&#xff0c;根本…

使用Optimum的BetterTransformer為常見的transformer結構模型進行推理加速

概述 &#x1f917; Optimum 提供了一個名為 BetterTransformer 的 API&#xff0c;這是標準 PyTorch Transformer API 的快速路徑&#xff0c;能夠通過稀疏性和融合內核&#xff08;如 Flash Attention&#xff09;在 CPU 和 GPU 上實現有趣的加速。目前&#xff0c;BetterTr…

一個 API 客戶端和一份 TS 學習手冊

第75期&#xff1a; Insomnia&#xff1a;超好看的 API 客戶端 項目介紹&#xff1a; 一款適用于 GraphQL、REST、WebSockets 和 gRPC 的開源 API 客戶端&#xff0c;顏值超高。 跨平臺&#xff0c;支持 Mac、Windows 和 Linux。但不支持網頁版&#xff0c;需要下載客戶端。…