<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【ESP32 在線語音】C++中constexpr 修飾詞的科普

      在C++中,const類型的變量默認具有內部鏈接性,因此可以安全地定義在.h文件中被多個.cpp文件包含。

      基本用法

      cpp
       
       
      // constants.h
      const int MAX_SIZE = 100;
      const double PI = 3.14159;
      const std::string APP_NAME = "MyApp";
      cpp
       
       
      // file1.cpp
      #include "constants.h"
      void func1() {
          std::cout << MAX_SIZE << std::endl;
      }
      cpp
       
       
      // file2.cpp  
      #include "constants.h"
      void func2() {
          std::cout << PI << std::endl;
      }

      為什么可以這樣做?

      • const變量在C++中默認有內部鏈接性

      • 每個包含該頭文件的.cpp文件都會獲得自己的副本

      • 不會產生重復定義的鏈接錯誤

      特殊情況

      1. 需要外部鏈接性的情況

      如果需要在多個文件間共享同一個const變量(比如取其地址),使用extern

      cpp
       
       
      // constants.h
      extern const int GLOBAL_CONST;  // 聲明
      
      // constants.cpp
      const int GLOBAL_CONST = 42;    // 定義

      2. constexpr變量

      constexpr默認有內部鏈接性,用法與const相同:

      cpp
       
       
      // constants.h
      constexpr int ARRAY_SIZE = 1024;
      constexpr double GRAVITY = 9.8;

      3. 需要避免的情況

      不要對非POD類型使用這種模式:

      cpp
       
       
      // 不推薦 - 每個翻譯單元都會構造一次
      const std::vector<int> DATA = {1, 2, 3};
      
      // 推薦使用靜態函數或內聯變量
      inline const std::vector<int>& getData() {
          static const std::vector<int> DATA = {1, 2, 3};
          return DATA;
      }

      現代C++的最佳實踐

      C++17引入的inline變量

      cpp
       
       
      // constants.h
      inline const int CONFIG_VALUE = 42;
      inline const std::string DEFAULT_NAME = "default";

      使用命名空間組織

      cpp
       
       
      // constants.h
      namespace constants {
          const int MAX_USERS = 1000;
          const double TIMEOUT = 30.0;
          constexpr int CACHE_SIZE = 256;
      }

      總結

      • 可以安全使用:基本類型的const變量定義在頭文件中

      • 推薦使用:constexpr、inline變量

      • ?? 注意:復雜類型可能每個翻譯單元都會構造一次

      • ?? 需要外部鏈接時:使用extern在.cpp文件中定義

      這種特性使得const常量成為在C++中定義編譯時常量的理想選擇。

       
       
       
       
       
       
       
       
       
       
       
       
      constexpr 和 const 有啥區別,另外constexpr 中的expr是什么的縮寫
       
       
       
       

      好的,這是一個非常核心的C++問題。我們來詳細拆解一下。

      首先,expr 是什么的縮寫?

      expr 是 "expression"(表達式)的縮寫。

      所以 constexpr 的全稱是 Constant Expression,即“常量表達式”。

      關鍵在于,它指定的對象或函數的值(或返回值)可以在編譯時就被計算出來


      const 與 constexpr 的核心區別

      雖然它們都表示“不變”,但應用的上下文和保證的嚴格程度完全不同。

      1. const - “運行時常量性”

      • 含義:“我只讀,在它的生命周期內不會被改變。”

      • 評估時機:值可以在運行時確定,也可以在編譯時確定。它只保證運行時的不變性。

      • 主要作用:創建一個只讀變量。

      2. constexpr - “編譯時常量性”

      • 含義:“我不僅是只讀的,而且我的值在編譯時就已經是已知的。”

      • 評估時機:值必須在編譯時就能被計算出來。

      • 主要作用:創建一個真正的編譯期常量,使得編譯器能夠進行優化,并允許其在只能使用編譯期常量的上下文中使用(如數組大小、模板參數、case標簽等)。


      代碼示例對比

      示例1:基礎類型

      cpp
       
       
      int get_value() { return 5; }
      
      int main() {
          // const: 運行時初始化(盡管這里編譯器可能優化)
          const int a = get_value(); // OK, a是運行時常量
      
          // constexpr: 編譯時初始化
          constexpr int b = 10; // OK, 10是字面量,編譯期可知
          // constexpr int c = get_value(); // 錯誤!get_value()不是constexpr函數,返回值無法在編譯期確定
      
          int arr1[a]; // C99可變長度數組,在C++中不是標準(有些編譯器擴展支持)
          int arr2[b]; // OK,因為b是編譯期常量,符合C++標準
      
          std::array<int, b> arr3; // OK,模板參數必須是編譯期常量
          // std::array<int, a> arr4; // 錯誤!a不是編譯期常量
      }

      示例2:函數

      constexpr 可以修飾函數,表示這個函數有可能在編譯期被調用(如果傳入的參數是編譯期常量的話)。

      cpp
       
       
      // 一個constexpr函數
      constexpr int square(int n) {
          return n * n;
      }
      
      int main() {
          const int a = 5;
          constexpr int b = 5;
      
          // 使用運行時參數調用constexpr函數
          const int result1 = square(a); // 可能在運行時計算
      
          // 使用編譯時參數調用constexpr函數
          constexpr int result2 = square(b); // 必須在編譯時計算
          constexpr int result3 = square(10); // 必須在編譯時計算
      
          int arr[square(5)]; // OK,square(5)是編譯期常量表達式
      }

      示例3:對象

      對于自定義類型,constexpr 構造函數意味著可以在編譯期構造該對象。

      cpp
       
       
      struct Point {
          constexpr Point(int x, int y) : x_(x), y_(y) {}
          constexpr int x() const { return x_; }
          constexpr int y() const { return y_; }
      private:
          int x_, y_;
      };
      
      int main() {
          // 在編譯期構造一個Point對象
          constexpr Point p(1, 2);
          // 在編譯期調用成員函數
          constexpr int x = p.x();
      
          // 這個Point是const的,但不一定在編譯期創建
          const Point q(3, 4); // 可能在運行時創建
      }

      總結對比表格

       
       
      特性 const constexpr
      核心含義 只讀,運行時不變 編譯期可知的常量
      評估時機 運行時 編譯時
      修飾變量 ? ?
      修飾函數 ? (成員函數表示不修改成員) ? (表示可在編譯期求值)
      修飾構造函數 ? ? (表示可在編譯期構造對象)
      可用作數組大小 ? (除非本身由常量表達式初始化) ?
      可用作模板參數 ? (除非本身由常量表達式初始化) ?
      靈活性 低(要求嚴格)

      現代C++中的建議

      1. 默認使用 constexpr:當你需要一個其值在編譯期就確定的常量時。

      2. 使用 const:當你只需要一個運行時只讀變量,或者其值需要在運行時才能確定時。

      3. 它們可以結合使用constexpr 變量默認就是 const 的。你經常會看到 constexpr const,但其中的 const 通常是冗余的。

      簡單來說:所有 constexpr 的對象都是 const 的,但并非所有 const 的對象都是 constexpr 的。 constexpr 是對 const 的“加強版”,增加了“編譯期可知”的嚴格保證。

       
       
       
       
       
       
       
       
       
       
       
       
      也就是說constexpr 是 有點像 #define 的
       
       
       
       

      這個類比非常到位!constexpr 確實在某種程度上可以看作是現代C++中類型安全、作用域明確的 #define 替代品。但它們之間仍有重要區別。

      相似之處

      1. 編譯期替換

      cpp
       
       
      // 使用 #define
      #define MAX_SIZE 100
      int arr1[MAX_SIZE];
      
      // 使用 constexpr
      constexpr int MAX_SIZE = 100;
      int arr2[MAX_SIZE];
      
      // 兩者都會在編譯時被替換為字面值

      2. 零運行時開銷

      cpp
       
       
      #define PI 3.14159
      constexpr double PI = 3.14159;
      
      // 編譯后都直接使用字面值,沒有內存訪問
      double area = PI * r * r;

      3. 可用于編譯期上下文

      cpp
       
       
      // 數組大小
      #define BUF_SIZE 256
      char buffer1[BUF_SIZE];
      
      constexpr int BUF_SIZE = 256;
      char buffer2[BUF_SIZE];
      
      // 模板參數
      template<int N> class Array {};
      Array<BUF_SIZE> arr; // 兩者都可以

      重要區別

      1. 類型安全

      cpp
       
       
      #define MAX_USERS 100     // 沒有類型,只是文本替換
      constexpr int MAX_USERS = 100; // 明確的int類型
      
      // #define 可能導致意外行為
      #define VALUE 2.5
      int x = VALUE; // 隱式轉換,可能丟失精度
      
      constexpr double VALUE = 2.5;
      int x = VALUE; // 明確的類型轉換,編譯器可能警告

      2. 作用域

      cpp
       
       
      // #define 沒有作用域,可能污染全局命名空間
      #define DEBUG 1
      
      void func() {
          #define INTERNAL 2 // 實際上還是全局的!
      }
      
      // constexpr 有明確的作用域
      namespace config {
          constexpr bool DEBUG = true;
      }
      
      void func() {
          constexpr int INTERNAL = 2; // 真正的局部作用域
      }

      3. 調試能力

      cpp
       
       
      #define VERSION "1.0"
      constexpr const char* VERSION = "1.0";
      
      // 調試時:
      // - #define 的 VERSION 不可見(已被替換)
      // - constexpr 的 VERSION 在調試器中可見

      4. 更強大的能力

      constexpr 比 #define 強大得多:

      cpp
       
       
      // constexpr 函數
      constexpr int factorial(int n) {
          return n <= 1 ? 1 : n * factorial(n - 1);
      }
      
      constexpr int fact_5 = factorial(5); // 編譯時計算
      
      // constexpr 對象
      struct Point {
          constexpr Point(int x, int y) : x(x), y(y) {}
          int x, y;
      };
      
      constexpr Point origin(0, 0);

      實際演進示例

      傳統C風格:

      cpp
       
       
      #define MAX_CONNECTIONS 1000
      #define DEFAULT_TIMEOUT 30
      #define APP_NAME "MyApp"

      現代C++風格:

      cpp
       
       
      namespace constants {
          constexpr int MAX_CONNECTIONS = 1000;
          constexpr std::chrono::seconds DEFAULT_TIMEOUT{30};
          constexpr std::string_view APP_NAME = "MyApp";
      }

      總結對比

       
       
      特性 #define constexpr
      類型安全 ? ?
      作用域 ? (全局) ? (有作用域)
      調試支持 ? ?
      C++特性 ? (預處理) ? (語言特性)
      函數能力 ? (宏函數) ? (真正的函數)
      對象支持 ? ?
      模板友好 ?? (有限) ?

      現代C++建議

      1. 完全用 constexpr 替換 #define 來定義常量

      2. 用 constexpr 函數替換宏函數

      3. 只在需要條件編譯時使用 #define

        cpp
         
         
        #ifdef DEBUG
            // 調試特定代碼
        #endif

      所以你的直覺是對的!constexpr 可以看作是 #define 的類型安全、現代化的繼承者,用于定義編譯期常量。

       
       
       
       
       
       
       
       
       
       
       
       
      那么在C語言里, const類型的變量可以定義在 .h 文件中被多個.cpp文件包含嗎
       
       
       
       

      這是一個很好的問題,它揭示了C和C++的一個重要區別。

      在C語言中,const類型的變量默認具有外部鏈接性,因此不能直接在.h文件中定義并被多個.c文件包含,否則會導致鏈接錯誤。

      問題演示

      c
       
       
      // constants.h
      const int MAX_SIZE = 100;        // 在C中,這是定義
      const double PI = 3.14159;       // 每個包含的.c文件都會有一份定義
      
      // file1.c
      #include "constants.h"
      void func1() {
          printf("%d\n", MAX_SIZE);
      }
      
      // file2.c  
      #include "constants.h"
      void func2() {
          printf("%f\n", PI);
      }

      編譯時會報重復定義錯誤:

      text
       
       
      multiple definition of `MAX_SIZE'
      multiple definition of `PI'

      為什么C和C++有這種區別?

      • C++const變量默認有內部鏈接性

      • Cconst變量默認有外部鏈接性

      這是C和C++語言設計的一個重要差異。

      C語言中的正確做法

      方法1:使用 extern(推薦)

      c
       
       
      // constants.h
      extern const int MAX_SIZE;        // 聲明
      extern const double PI;           // 聲明
      
      // constants.c
      const int MAX_SIZE = 100;         // 定義
      const double PI = 3.14159;        // 定義
      
      // file1.c
      #include "constants.h"            // 使用聲明
      void func1() {
          printf("%d\n", MAX_SIZE);     // 鏈接到constants.c中的定義
      }
      
      // file2.c
      #include "constants.h"            // 使用聲明  
      void func2() {
          printf("%f\n", PI);           // 鏈接到constants.c中的定義
      }

      方法2:使用 static(每個文件獨立副本)

      c
       
       
      // constants.h
      static const int MAX_SIZE = 100;      // 每個包含的文件有獨立副本
      static const double PI = 3.14159;     // 每個包含的文件有獨立副本
      
      // file1.c
      #include "constants.h"                // 獲得自己的MAX_SIZE和PI副本
      // file2.c
      #include "constants.h"                // 獲得自己的MAX_SIZE和PI副本

      方法3:使用宏(傳統C風格)

      c
       
       
      // constants.h
      #define MAX_SIZE 100
      #define PI 3.14159
      
      // 所有包含的文件共享這些宏定義

      方法4:使用枚舉(僅限整數)

      c
       
       
      // constants.h
      enum {
          MAX_SIZE = 100,
          BUFFER_SIZE = 256
      };
      // 枚舉常量有內部鏈接性,可以安全包含

      現代C的補充(C99以后)

      使用 inline(C99標準)

      c
       
       
      // constants.h
      // 在頭文件中提供定義,但避免重復定義錯誤
      extern inline const int MAX_SIZE() { return 100; }
      extern inline const double PI() { return 3.14159; }
      
      // 使用方式變成函數調用
      printf("%d\n", MAX_SIZE());

      使用 _Static_assert(C11)進行編譯期檢查

      c
       
       
      // constants.h
      extern const int MAX_SIZE;
      _Static_assert(MAX_SIZE > 0, "MAX_SIZE must be positive"); // 編譯期斷言

      總結對比

       
       
      方法 優點 缺點
      extern 單一定義,節省內存 需要額外的.c文件
      static 使用簡單 每個文件有副本,浪費內存
      編譯期替換,零開銷 無類型,調試困難
      枚舉 類型安全,編譯期常量 僅適用于整數

      最佳實踐建議

      1. 對于需要共享的const變量:使用extern方法

      2. 對于小的、整型常量:使用枚舉

      3. 對于不需要共享的常量:使用static const

      4. 保持兼容性:如果代碼需要在C和C++中編譯,使用extern方法

      所以記住這個關鍵區別:在C中,const變量有外部鏈接性;在C++中,const變量有內部鏈接性。這就是為什么在C中不能簡單地把const定義放在頭文件中的原因。

      posted @ 2025-10-28 01:49  FBshark  閱讀(17)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 精品久久久中文字幕一区| 成人一区二区三区在线午夜| 熟女精品国产一区二区三区| 樱桃熟了a级毛片| а∨天堂一区中文字幕| 黑人玩弄人妻中文在线| 亚洲av色一区二区三区| 激情国产一区二区三区四区| 亚洲欧美在线观看品| 亚洲天堂男人的天堂在线| 亚洲色成人一区二区三区人人澡人人妻人人爽人人蜜桃麻豆 | 亚洲欧洲日产国码无码久久99| 国产偷国产偷亚洲高清日韩| 国产免费高清69式视频在线观看 | 青青青爽在线视频观看| 99国产精品白浆无码流出 | 国产av一区二区不卡| 国产农村激情免费专区| 亚洲av片在线免费观看| 亚洲精中文字幕二区三区| 亚洲男人第一无码av网站| 天堂中文8资源在线8| 国产精品亚洲二区亚瑟| 九九综合va免费看| 国产日韩久久免费影院| 麻豆亚洲自偷拍精品日韩另| 最新亚洲人成网站在线观看| 国产超碰无码最新上传| 久久精品国产亚洲av麻豆小说| 中文激情一区二区三区四区| 亚洲天堂激情av在线| 国产成人精品无码专区| 亚洲天堂一区二区三区四区| 最新亚洲人成网站在线影院| 富阳市| 亚洲国产午夜精品福利| 欧美熟妇性XXXX欧美熟人多毛| 好爽毛片一区二区三区四| 五月婷婷久久中文字幕| 中文字幕熟妇人妻在线视频| 成人午夜激情在线观看|