成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C++ 面試題:C++中 constexpr 函數(shù)的限制有哪些?

開(kāi)發(fā)
在 C++ 中,字面類型(Literal Type) 是指可以在編譯期確定其值的類型,是支持編譯期計(jì)算的基礎(chǔ)。

注意這道面試題,問(wèn)的不是 constexpr 的用法,是限制有哪些?

一、基本限制

參數(shù)和返回類型必須是字面類型。

我們理解下什么是字面類型?

在 C++ 中,字面類型(Literal Type) 是指可以在編譯期確定其值的類型,是支持編譯期計(jì)算的基礎(chǔ)。

1. C++ 標(biāo)準(zhǔn)規(guī)定,以下類型屬于字面類型:

(1) 基本類型

int, char, bool, float, double, long, short, unsigned 等。

nullptr_t(C++11 起)。

constexpr int x = 42;  // int 是字面類型
constexpr char c = 'A'; // char 是字面類型

(2) 引用類型

引用必須綁定到字面類型。

constexpr int a = 10;
constexpr const int& ref = a;  // 引用是字面類型

(3) 數(shù)組類型

數(shù)組的元素必須是字面類型。

constexpr int arr[] = {1, 2, 3};  // int[] 是字面類型

(4) 字面值類(Literal Class)

類的所有非靜態(tài)成員必須是字面類型。

必須有一個(gè) constexpr 構(gòu)造函數(shù)(可以是默認(rèn)構(gòu)造函數(shù)或帶參數(shù)的構(gòu)造函數(shù))。

不能有虛函數(shù)。(C++20允許字面類型包含虛函數(shù),但是需要滿足不少條件)

struct Point {  // 字面值類
    int x, y;
    constexpr Point(int x = 0, int y = 0) : x(x), y(y) {}  // constexpr 構(gòu)造函數(shù)
};
constexpr Point p(1, 2);  // 編譯期構(gòu)造

(5) void(C++14 起)

void 也可以算作字面類型,但通常不能直接用于 constexpr 變量。

(6) 標(biāo)準(zhǔn)庫(kù)中的某些類型

std::array(如果 T 是字面類型)。

std::string_view(C++17 起)。

#include <array>
constexpr std::array<int, 3> arr = {1, 2, 3};  // std::array 是字面類型

constexpr std::string_view sv = "compile-time"; // 合法,數(shù)據(jù)是編譯期字面量
// constexpr std::string_view sv2 = std::string("runtime"); // 錯(cuò)誤:非編譯期數(shù)據(jù)

std::string("runtime") 會(huì)創(chuàng)建一個(gè)臨時(shí) std::string 對(duì)象,它的底層數(shù)據(jù)(存儲(chǔ)字符的數(shù)組)在內(nèi)存中的生命周期僅限于當(dāng)前表達(dá)式。當(dāng)這行代碼執(zhí)行完畢時(shí),臨時(shí)對(duì)象會(huì)被銷毀,其底層數(shù)據(jù)也隨之失效。

std::string("runtime") 生成的臨時(shí)對(duì)象在編譯期上下文中仍然會(huì)“邏輯銷毀”,導(dǎo)致 string_view 引用的底層數(shù)據(jù)在編譯期就失效。

這里最關(guān)鍵的就是數(shù)據(jù)來(lái)源的編譯期確定性!

2. 非字面類型的例子

以下類型不是字面類型,因此不能用于 constexpr 上下文:

  • std::string(因?yàn)樗膭?dòng)態(tài)內(nèi)存分配不能在編譯期確定)。
  • 帶有虛函數(shù)的類(C++20 之前)。
  • 包含非字面類型成員的類。
struct NonLiteral {
    std::string s;  // std::string 不是字面類型
    NonLiteral() {}  // 沒(méi)有 constexpr 構(gòu)造函數(shù)
};
// constexpr NonLiteral nl;  // 錯(cuò)誤:NonLiteral 不是字面類型

3. 為什么 constexpr 限制要求字面類型?

constexpr 的核心目標(biāo)是編譯期計(jì)算,因此:

  • 編譯期可構(gòu)造:字面類型的對(duì)象可以在編譯期初始化。
  • 編譯期可求值:constexpr 函數(shù)的參數(shù)和返回值必須是編譯期可確定的。
  • 避免運(yùn)行時(shí)依賴:非字面類型(如 std::string)可能涉及動(dòng)態(tài)內(nèi)存分配,無(wú)法在編譯期處理。

二、禁止的操作

以下操作在 constexpr 函數(shù)中不允許出現(xiàn):

1. 動(dòng)態(tài)內(nèi)存分配

用new/delete 或堆內(nèi)存操作。

constexpr int* invalid() {
    int* p = new int(42); // 錯(cuò)誤:不能在編譯時(shí)分配內(nèi)存
    return p;
}

2. 異常處理

不能使用 throw 或 try-catch。

constexpr int unsafe(int a) {
    if (a < 0) throw "negative"; // 錯(cuò)誤:不允許異常
    return a;
}

3. 調(diào)用非 constexpr 函數(shù)

只能調(diào)用其他 constexpr 函數(shù)或編譯器內(nèi)建函數(shù)

int non_constexpr(int x) { return x; }

constexpr int invalid_call(int x) {
    return non_constexpr(x); // 錯(cuò)誤:調(diào)用了非 constexpr 函數(shù)
}

4. 修改全局/靜態(tài)變量

編譯時(shí)上下文無(wú)法處理副作用。

全局變量:在程序啟動(dòng)時(shí)(main() 之前)初始化。

靜態(tài)變量:

  • 局部 static 變量在第一次進(jìn)入作用域時(shí)初始化(運(yùn)行時(shí))。
  • 全局 static 變量類似于全局變量。

由于它們的初始化可能依賴運(yùn)行時(shí)狀態(tài),constexpr 無(wú)法保證編譯期確定性。

int global = 0;
constexpr void modify_global() {
    global++; // 錯(cuò)誤:修改全局變量
}

C++標(biāo)準(zhǔn)規(guī)定,constexpr函數(shù)中不能包含對(duì)具有靜態(tài)存儲(chǔ)期變量的賦值或修改操作。

三、成員函數(shù)的特殊規(guī)則

1. 虛函數(shù)

  • C++20 前:虛函數(shù)不能是 constexpr。
  • C++20 起:允許虛函數(shù)為 constexpr。
struct Base {
    virtual constexpr int foo() { return 1; } // C++20 合法
};

2. 隱式 const 限定(C++11)

  • C++11:constexpr 成員函數(shù)隱式為 const。
  • C++14:取消此限制,允許修改對(duì)象狀態(tài)。
struct Widget {
    int value = 0;
    constexpr void update() { value++; } // C++14+ 合法
};

這里其實(shí)開(kāi)始不是很理解,成員變量的修改其實(shí)是運(yùn)行時(shí)行為,但是現(xiàn)在要在編譯期搞,查了下資料是這么說(shuō)的:

constexpr成員函數(shù)修改成員變量,在編譯期是邏輯行為,運(yùn)行時(shí)才是真實(shí)修改
。是邏輯上的(編譯器模擬,不生成實(shí)際的內(nèi)存寫(xiě)入)。

我理解是:

  • 對(duì) value 的修改發(fā)生在編譯期,最終生成的 value 是一個(gè)編譯期常量對(duì)象,其狀態(tài)被“凍結(jié)”為 count = 1。
  • 沒(méi)有運(yùn)行時(shí)開(kāi)銷,value 的值直接編譯進(jìn)二進(jìn)制。
  • 這里的“修改”只是邏輯上的操作,不涉及真實(shí)內(nèi)存寫(xiě)入。
  • 運(yùn)行時(shí)調(diào)用 update() 是真正的運(yùn)行時(shí)行為,修改的是內(nèi)存中的對(duì)象。
  • 代碼邏輯與編譯期版本相同,但發(fā)生在程序運(yùn)行時(shí)。
  • 對(duì)比上面說(shuō)的全局變量,類成員變量的對(duì)象是局部的影響可控,全局變量可能被其他地方修改,所以類成員變量這里可以放開(kāi),但是全局變量不行。

四、遞歸深度限制

即使遞歸邏輯合法,編譯器對(duì) constexpr 遞歸深度有默認(rèn)限制(如 GCC 默認(rèn) 512 層)。超出限制時(shí)需通過(guò)編譯選項(xiàng)調(diào)整:

g++ -fconstexpr-depth=1000 main.cpp

五、版本差異總結(jié)

特性

C++11

C++14+

C++20

函數(shù)體復(fù)雜度

單條

允許循環(huán)、變量

進(jìn)一步擴(kuò)展

虛函數(shù)支持

不支持

不支持

支持

成員函數(shù)隱式

示例:合法與非法用法對(duì)比

// 合法:C++14+ 允許循環(huán)和局部變量
constexprintsum(int n){
    int total = 0;
    for (int i = 0; i < n; ++i) {
        total += i;
    }
    return total;
}

// 非法:動(dòng)態(tài)內(nèi)存分配
constexprint* create(){
    int* p = newint(10);
    return p;
}

// 合法:C++20 虛函數(shù)
structBase {
    virtualconstexprintget(){ return1; }
};


責(zé)任編輯:趙寧寧 來(lái)源: CppPlayer
相關(guān)推薦

2025-05-20 10:00:00

C++命名空間別名代碼

2025-05-20 08:10:00

函數(shù)函數(shù)類型函數(shù)指針類型

2021-10-27 11:00:30

C++語(yǔ)言面試

2024-02-21 23:13:45

C++編程開(kāi)發(fā)

2010-01-26 10:42:26

C++函數(shù)

2010-01-27 17:16:52

C++構(gòu)造函數(shù)

2023-10-08 08:48:38

C++constexpr

2010-01-19 13:43:59

C++函數(shù)

2025-05-26 03:20:00

2011-03-29 14:31:41

CC++

2025-05-27 10:15:00

void*函數(shù)開(kāi)發(fā)

2025-04-30 10:10:00

在 C++C++11Lambda

2010-01-21 09:34:57

C++語(yǔ)法

2010-01-27 16:05:06

C++堆棧

2025-05-09 09:25:00

2010-01-21 14:07:14

CC++聲明

2025-05-06 08:20:00

互斥鎖C++編程

2010-01-20 10:19:55

C++數(shù)組

2010-01-25 10:25:19

C++變量

2010-01-28 16:31:54

C++類型
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久一热 | 久久伦理电影 | 国产一区精品在线 | 国产精品久久久久久久久免费 | 欧美在线观看一区 | 国产精品日韩在线观看一区二区 | 国产精品中文字幕在线 | 日韩av在线一区二区三区 | 色狠狠一区 | 一区二区久久精品 | 亚洲高清在线观看 | 日韩高清在线观看 | 国产日韩欧美一区二区在线播放 | 亚洲色图综合 | 免费国产视频在线观看 | 国内精品一区二区三区 | 亚洲91精品 | 成人美女免费网站视频 | 成人做爰www免费看视频网站 | 一级黄色av电影 | 日韩精品免费 | 国产精品久久久久久久7777 | 日韩在线观看中文字幕 | 亚洲精品视频一区 | 欧美日韩国产传媒 | 1000部精品久久久久久久久 | 午夜天堂精品久久久久 | 欧美8一10sex性hd| 视频一区在线观看 | 日韩精品一区二区三区在线观看 | 国产成人精品一区二三区在线观看 | 久久久一区二区三区四区 | 激情黄色在线观看 | 成人毛片视频免费 | 国产成人免费视频 | 国产精品久久久久久福利一牛影视 | 日韩精品一区二区三区中文字幕 | 欧美一区二区三区在线观看 | 色综合天天天天做夜夜夜夜做 | 国际精品鲁一鲁一区二区小说 | 亚洲黄色一级 |