std::ratio<1,1000> 是什么意思?


author: hjjdebug
date: 2025年 05月 14日 星期三 09:45:24 CST
description: std::ratio<1,1000> 是什么意思?


文章目錄

    • 1. 它是一種數值嗎?
    • 2. 它是一種類型嗎?
    • 3. std:ratio 是什么呢?
    • 4. 分析一個展開后的模板函數
    • 5.小結:

前言: std::ratio 是c++11中引入的模板類.表示比例.
靠,連個比值都定義一個類,我相信c++已經做了很多類了.
想干什么事,一般找到調用方法就可以了.
這個類先假定它很復雜, 等讀完會發現它很簡單!

先給一個簡單的例子來研究.

$ cat main.cpp
#include <iostream>
#include <ratio>
using namespace std;
// 定義一個模板函數,接受一個 std::ratio 類型參數
// 這個類型有靜態變量num 和den, 由于是靜態變量,會直接在代碼中用常數展開.
// 這個模板函數將來會生成很多個函數,不同的類型就會生成不同的函數代碼,是靜態編譯多態性的一種
template <typename Ratio>
void print_ratio() {printf("num:%ld,den:%ld\n",Ratio::num,Ratio::den);
}int main() {using r=std::ratio<1,1000>; //using 就是typedef, 編譯時直接替換// std::ratio<1,1000> 是個類型, 而非數值,//這里類型名會與函數名共同構成一個代碼中的導出函數名叫print_ratio<std::ratio<1l,1000l>>print_ratio<r>(); // 輸出 Numerator: 1, Denominator: 1000// 這里std::ratio<1,10>時另一種類型,是分子為1,分母為10的類型print_ratio<std::ratio<1,10>>();//用類型實例化對象std::ratio<1,1000> obj;cout<<"num:"<<obj.num<<",den:"<<obj.den<<endl;cout<<"size_type:"<<sizeof(std::ratio<1,1000>)<<",size_obj:"<<sizeof(obj)<<endl;return 0;
}

執行:
./temp3
num:1,den:1000
num:1,den:10
num:1,den:1000
size_type:1,size_obj:1

代碼中, std::ratio<1,1000> 是什么意思呢?

1. 它是一種數值嗎?

它不是數值
看一下gdb 中的打印
p std::ratio<1,1000>
Attempt to use a type name as an expression

2. 它是一種類型嗎?

它是一種類型.
看一下 gdb 的打印
ptype std::ratio<1,1000>
type = struct std::ratio<1, 1000> {
static const intmax_t num;
static const intmax_t den;
}
這個類型包含兩個靜態成員變量
p std::ratio<1,1000>::num
$1 = 1
p std::ratio<1,1000>::den
$2 = 1000

可見類型也可以包含屬于自己的數值. 這2個數值在函數中用Ratio::num, Ratio::den引用過.

3. std:ratio 是什么呢?

顯然它是一個模板類,因為有<>,有兩個模板參數,因為給了1,1000
這樣就可以由這個模板類,根據模板參數的不同,創建很多個類.
這里所說的類,就是類型.注意,只是類型,不是對象. 你可以用類型實例化一個對象,就像代碼中那樣.
下面看模板類的定義:

  template<intmax_t _Num, intmax_t _Den = 1>struct ratio{static constexpr intmax_t num =_Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value;static constexpr intmax_t den =__static_abs<_Den>::value / __static_gcd<_Num, _Den>::value;typedef ratio<num, den> type;};

這個結構看起來還是有點復雜,
static 修飾的變量叫靜態變量,它是屬于類的而不屬于對象.
constexpr 表示它會在編譯期計算出數值
intmax_t 是 long int 的別名
__static_sign<_Den>::value, 這也是一個模板類,拿到這個類的帶符號的分母的value值.
__static_gcd<_Num, _Den>::value, 拿到gcd模板類的value值,該值是_Num,_Den 的最大公約數.
__static_abs<_Den>::value, 分母絕對值模板類的value值

我們假定分子,分母互質, 即gcd(num,den)=1, 分子,分母都為正數,則上式可以簡化為:

template<intmax_t _Num, intmax_t _Den = 1>
struct ratio
{
static constexpr intmax_t num = _Num;
static constexpr intmax_t den = _Den;
};
這樣就看清了,ratio 是一個帶2參數的模板類, constexpr 的含義是編譯時就付給值.

4. 分析一個展開后的模板函數

模板函數 template
void print_ratio();
當類型std::ratio<1,1000> 與函數名 print_ratio相遇時
共同構成一個完整的導出函數名叫print_ratio<std::ratio<1l,1000l>>
該名稱才是真實的函數導出名稱(已經被c++filt 過濾過).
真實名稱是這樣的:_Z11print_ratioISt5ratioILl1ELl1000EEEvv,不是給人看的,給編譯器看的.
下面是函數 print_ratio<std::ratio<1l,1000l>> 的反匯編代碼.
是的,函數名稱是可以帶角標及逗號等字符的,比c常用的字符下化線豐富了不少.
重點注釋了函數中怎樣使用類型std::ratio<1,1000>中的靜態成員變量num及den, 就是直接用數值.

/*(gdb) disassemble/m print_ratio<std::ratio<1l, 1000l> >
Dump of assembler code for function print_ratio<std::ratio<1l, 1000l> >():
9	void print_ratio() {0x0000555555555203 <+0>:	endbr64 0x0000555555555207 <+4>:	push   %rbp0x0000555555555208 <+5>:	mov    %rsp,%rbp10		printf("num:%ld,den:%ld\n",Ratio::num,Ratio::den);0x000055555555520b <+8>:	mov    $0x3e8,%edx   //類中的靜態成員,直接給1000數值為第3參數0x0000555555555210 <+13>:	mov    $0x1,%esi     //類中靜態成員,直接給1數值為第2參數0x0000555555555215 <+18>:	lea    0xde8(%rip),%rdi        # 0x5555555560040x000055555555521c <+25>:	mov    $0x0,%eax0x0000555555555221 <+30>:	callq  0x555555555070 <printf@plt>11	}0x0000555555555226 <+35>:	nop0x0000555555555227 <+36>:	pop    %rbp0x0000555555555228 <+37>:	retq   End of assembler dump.*/

5.小結:

  1. 模板參數可以是整形數,例如上邊的1,1000
  2. 類型名稱可以帶角標. 例:std::ratio<1,1000>
  3. 類型可以包含屬于自己的數值. 例Ratio::num, Ratio::den
  4. 類型可以與函數名一起構成實例化后的模板函數名稱. print_ratio<std::ratio<1l,1000l>>
  5. 類型實例化后的對象可以不包含任何數值. sizeof(obj)=1
  6. 類型的運行期大小也可以為0. sizeof(std::ratio<1,1000>=1,
    說明它包含的類成員變量都是編譯器的常數. 例Ratio::num=1,Ratio::den=1000
  7. 一個模板類std::ratio<intmax_t num,intmax_t den>,能實例化出很多實例化類,
    std::ratio<1,1000>只是其中之一. 可以隨心所欲創造很多種類型,例std::ratio<1,10)等.
  8. 類型是跟gcc 的一種約定,你定義了這種類型,gcc就認識了這種類型,你就可以使用這種類型.

言之不盡,c++相較與c而言, 有更多的內涵需要讓gcc明白, gcc會理解我們更復雜的表達方式.

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

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

相關文章

測試--測試分類 (白盒 黑盒 單元 集成)

一、按照測試目標分類&#xff08;測試目的是什么&#xff09; 主類別細分說明1. 界面測試UI內容完整性、一致性、準確性、友好性&#xff0c;布局排版合理性&#xff0c;控件可用性等2. 功能測試檢查軟件功能是否符合需求說明書&#xff0c;常用黑盒方法&#xff1a;邊界值、…

整理了 2009 - 2025 年的【199 管綜真題 + 解析】PDF,全套共 34 份文件

每年真題原卷 ? 每年詳細解析 ? &#x1f4c2;【管綜真題 2009-2025】 &#x1f4c2;【管綜解析 2009-2025】 目錄樹&#xff1a; ├── 2009-2025管綜真題 PDF │ ├── 2009年199管綜真題.pdf │ ├── 2010年199管綜真題.pdf │ ├── 2011年199管綜真題.pd…

用golang實現二叉搜索樹(BST)

目錄 一、概念、性質二、二叉搜索樹的實現1. 結構2. 查找3. 插入4. 刪除5. 中序遍歷 中序前驅/后繼結點 一、概念、性質 二叉搜索樹&#xff08;Binary Search Tree&#xff09;&#xff0c;簡寫BST&#xff0c;又稱為二叉查找樹 它滿足&#xff1a; 空樹是一顆二叉搜索樹對…

自動化:批量文件重命名

自動化&#xff1a;批量文件重命名 1、前言 2、效果圖 3、源碼 一、前言 今天來分享一款好玩的自動化腳&#xff1a;批量文件重命名 有時候呢&#xff0c;你的文件被下載下來文件名都是亂七八糟毫無規律&#xff0c;但是當時你下載的時候沒辦法重名或者你又不想另存為重新重…

VueUse/Core:提升Vue開發效率的實用工具庫

文章目錄 引言什么是VueUse/Core&#xff1f;為什么選擇VueUse/Core&#xff1f;核心功能詳解1. 狀態管理2. 元素操作3. 實用工具函數4. 瀏覽器API封裝5. 傳感器相關 實戰示例&#xff1a;構建一個拖拽上傳組件性能優化技巧與原生實現對比常見問題解答總結 引言 在現代前端開發…

stm32 ADC單通道轉換

stm32c8t6僅有12位分辨率 1、單次轉換 非掃描 1、初始化 void Ad_Init() {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//配置ADCCLK時鐘分頻,ADC的輸入時鐘不得超過14MHzRCC_ADCCLKConfig(RCC_PCLK2_Div6);G…

2KW壓縮機驅動參考設計【SCH篇】

實物展示&#xff1a; ACDC: VAC和VAC-為交流電壓檢測&#xff1a; 1.C33 C34作為Y電容走線寬度要求&#xff1a; Y電容一般用于L/N到地之間&#xff08;L-PE 或 N-PE&#xff09;&#xff0c;主要作用是抑制共模干擾。其走線的電流非常小&#xff0c;推薦使用 ≥ 1mm 寬的走…

python05——循環結構

1、while循環 n0 #初始條件 while n<5: #判斷print(hello python) #要重復執行的代碼print(n) #注意同級代碼縮進相同n1 #計數器結果&#xff1a; hello python 0 hello python 1 hello python 2 hello python 3 hello python 4 hello python 5 #求階乘和 sum0 n1 whil…

LINUX編譯、運行、測試lowcoder_CN

參考 二者沒有太大差異。 LINUX編譯、運行、測試lowcoder-CSDN博客 下載 git clone https://github.com/mousheng/lowcoder_CN 或 git clone https://gitcode.com/gh_mirrors/lo/lowcoder_CNcd lowcoder_CN三個模塊 node-service api-service client 每個模塊都有自己的…

Python 基礎之函數命名

幾個問題 使用描述性蛇形命名法&#xff08;snake_case&#xff09;Python函數名應使用什么大小寫格式&#xff1f;為什么函數名要具有描述性&#xff1f;方法的命名規范是什么&#xff1f;函數、變量和類的命名有何區別&#xff1f; Python函數的命名有一些不可違背的硬性規…

redis 命令大全整理

http://doc.redisfans.com/ 原網址 Redis 命令分類 Key(鍵) Key(鍵)命令 exists/del/keys/type/scanobject/move/dump/migratettl/pttl/persist/expireat/pexpireat/expire/pexpirerename/renamenxsort/randomkey/restoreexists 語法:exists key [key ...] 檢查一個或多…

React中useDeferredValue與useTransition終極對比。

文章目錄 前言一、核心差異對比二、代碼示例對比1. useDeferredValue&#xff1a;延遲搜索結果更新2. useTransition&#xff1a;延遲路由切換 三、應用場景總結四、注意事項五、原理剖析1. 核心機制對比2. 關鍵差異3. 代碼實現原理 總結 前言 在React的并發模式下&#xff0c…

高并發內存池|定長內存池的設計

二、定長內存池的設計 設計一個定長的內存池&#xff0c;這個內存池的定長在于&#xff0c;當剩余空間使用完畢后&#xff0c;總是開辟相同長度的新空間來使用。我們會使用到一個指針來切割劃分大空間為小空間。大空間是內存池向系統申請的內存大小&#xff0c;而小空間是程序…

微信小程序 自定義圖片分享-繪制數據圖片以及信息文字

一 、需求 從數據庫中讀取頭像&#xff0c;姓名電話等信息&#xff0c;當分享給女朋友時&#xff0c;每個信息不一樣 二、實現方案 1、先將數據庫中需要的頭像姓名信息讀取出來加載到data 數據項中 data:{firstName:, // 姓名img:, // 頭像shareImage:,// 存儲臨時圖片 } 2…

從零開始理解Jetty:輕量級Java服務器的入門指南

目錄 一、Jetty是什么&#xff1f;先看一個生活比喻 二、5分鐘快速入門&#xff1a;搭建你的第一個Jetty服務 步驟1&#xff1a;Maven依賴配置 步驟2&#xff1a;編寫簡易Servlet&#xff08;廚房廚師&#xff09; 步驟3&#xff1a;組裝服務器&#xff08;餐廳開業準備&am…

深入淺出IIC協議 - 從總線原理到FPGA實戰開發 -- 第一篇:I2C總線協議深度解剖

第一篇&#xff1a;I2C總線協議深度解剖 副標題 : 兩根線如何征服千億設備&#xff1f;詳解硬件工程師必須掌握的通信奧義 1. 為什么I2C仍是嵌入式經典&#xff1f; 1.1 總線拓撲的哲學 拓撲對比圖 SPI需4線N片選 vs I2C僅2線級聯 UART點對點 vs I2C多主從架構 成本控制實…

MySQL 索引優化以及慢查詢優化

在數據庫性能優化中&#xff0c;索引優化和慢查詢優化是兩個關鍵環節。合理使用索引可以顯著提高查詢效率&#xff0c;而識別和優化慢查詢則能提升整體數據庫性能。本文將詳細介紹MySQL索引優化和慢查詢優化的方法和最佳實踐。 一、MySQL 索引優化 1.1 索引的基本概念 索引是…

vue使用Pinia實現不同頁面共享token

文章目錄 一、概述二、使用步驟安裝pinia在vue應用實例中使用pinia在src/stores/token.js中定義store在組件中使用store登錄成功后&#xff0c;將token保存pinia中向后端API發起請求時&#xff0c;攜帶從pinia中獲取的token 三、參考資料 一、概述 Pinia是Vue的專屬狀態管理庫…

通俗版解釋CPU、核心、進程、線程、協程的定義及關系

通俗版解釋&#xff08;比喻法&#xff09; 1. CPU 和核心 CPU 一個工廠&#xff08;負責干活的總部&#xff09;。核心 工廠里的車間&#xff08;比如工廠有4個車間&#xff0c;就能同時處理4個任務&#xff09;。 2. 進程 進程 一家獨立運營的公司&#xff08;比如一家…

用 VS Code / PyCharm 編寫你的第一個 Python 程序

用ChatGPT做軟件測試 編寫你的第一個 Python 程序——不只是“Hello, World”&#xff0c;而是構建認知、習慣與未來的起點 “第一行代碼&#xff0c;是一個開發者認知世界的方式。” 編程的入門&#xff0c;不只是運行一個字符串輸出&#xff0c;更是開始用計算機思維來理解、…