C++11:constexpr 編譯期性質

C++11:constexpr & 編譯期性質

    • 常量表達式 constexpr
      • 變量
      • IiteralType
      • 函數
    • 自定義字面量
      • 參數匹配與重載規則
    • 靜態斷言


常量表達式 constexpr

const expression常量表達式,是C++11引入的新特性,用于將表達式提前到編譯期進行計算,從而減少運行時的重復計算,提高運行時效率。該特性基于關鍵字constexpr,可以用于修飾變量,函數等。

變量

其實在C++11之前,C++默認就會把 const int 進行編譯期計算,從而優化運行時效率,但是這個過程是隱式的。

例如以下代碼:

int c1 = 1 + 20 * 5;
const int a = 500;
int c2 = a + 1 * 2;
int c3 = c2 + 1;

此處對于c1ac2都是在編譯期就可以確認值的,但是c3需要運行時才會確認值。

  • c1:由于表達式中所有值都是字面量,因此在編譯期就可以確定整個表達式的值,從而初始化c1

    匯編代碼如下:

    C7 45 04 65 00 00 00 mov         dword ptr [c1],65h  
    

    此處65h就是1 + 20 * 5的十六進制值,匯編階段直接計算出來并且賦值到變量c1了。

  • a:表達式直接賦值字面量500,同理編譯期就可以確定值

    匯編代碼如下:

    C7 45 24 F4 01 00 00 mov         dword ptr [a],1F4h  
    

    c1同理,1F4h就是十六進制的500

  • c2:表達式中a是一個const int變量,說明后續不會發生修改,又在編譯期就已經確認初始值,所以整個表達式 a + 1 * 2 也是可以在編譯期確認值的。

    匯編代碼如下:

    C7 45 44 F6 01 00 00 mov         dword ptr [c2],1F6h  
    

    這里也是直接計算了500 + 1 * 2 的十六進制,賦值到c2

  • c3:此處表達式中,c2不是一個const變量,因此就算編譯期確定它的初始值,也無法保證后續不會被修改,因此需要運行時推斷。

    匯編代碼如下:

    8B 45 44             mov         eax,dword ptr [c2]  
    FF C0                inc         eax  
    89 45 64             mov         dword ptr [c3],eax
    

    首先把c2變量的值加載到eax寄存器里面,然后inc指令對eax里面的值加一,最后把eax自增后的值賦值到c3,整個過程是運行時完成的。

以上四行代碼的解析,可以得出C++本身是會對表達式進行優化的,如果表達式在編譯期就可以求出結果,編譯器就有可能在編譯階段求出其具體值,而不是在運行時計算。

并且對于const int(整形,枚舉,且有初始值),編譯器本身會盡可能讓其在編譯期進行計算,成為一個常量表達式,但是對于const修飾的其他類型不做此要求,有可能在編譯期也有可能在運行時

在C++11,拓寬了對這個編譯期計算特性的普適性,引入了constexpr關鍵字,被其修飾的變量,一定會在編譯期得到結果,如果無法得到結果,那么就會報錯。

  • 修飾變量語法:
constexpr type name = expression;

此處的expression必須滿足:

  1. 編譯期可以確定值
  2. 確定后不會再修改
  3. 不為空,即變量必須初始化

例如:

constexpr int c1 = 1 + 20 * 5;
constexpr int c2 = c1 + 500; // success

此處的c1c2都是合法的常量表達式,在編譯期可以進行求值。

此外,const int 也是可以初始化 constexpr int 的:

const int c1 = 1 + 20 * 5;
constexpr int c2 = c1 + 500; // success

因為剛剛提到,const int(整形家族,枚舉)是會隱式在編譯期就盡可能求值的,那么它滿足 編譯期求值 + 后續不修改 兩大特性,就可以初始化constexpr

但是以下代碼又是錯誤的:

int a = 1;
const int c1 = a + 20 * 5;
constexpr int c2 = c1 + 500; // error

此處代碼相比之前,就是c1初始化的時候依賴了普通變量a,但是a無法在編譯期求值,自然c1也就無法在編譯期求值,進而導致c2無法在編譯期求值,constexpr報錯。

剛才高亮語句也說明了,const int 只是盡可能在編譯期進行求值,如果不行,那么const int 就無法進一步初始化constexpr int

但是對于整形家族和枚舉以外的類型,const是絕不能修飾constexpr的,例如:

const double d1 = 3.14;
constexpr double d2 = d1 * 3; // error

此處就算d1可以在編譯期確定值,并且const特性保證后續不會修改。但是C++標準并沒有對此明確規定,d1也有可能會在運行時得到值,這取決于編譯器,所以const double 無法初始化constexpr double

最后,就算是const int,如果被volatile修飾,也不能用于初始化constexpr,例如:

volatile const int c1 = 1 + 20 * 5;
constexpr int c2 = c1 + 500; // error

因為volatile const表示,這個變量就算是const,也是有可能被修改的,那么就不滿足constexpr的第二個要求。

前面這一大段,主要闡述了constexpr初始化的幾個場景,總結一下:

  1. const int(整型家族,枚舉):在編譯期可以確定值,并且不被volatile修飾
  2. const 其它:不論如何都不能拿來初始化constexpr
  3. constexpr 任意:都可以拿來初始化其他的constexpr表達式,也是最佳實踐

IiteralType

并不是所有的變量都可以被constexpr修飾,并在編譯期求值的,比如:

constexpr std::string str = "hello";

這行代碼是會報錯的,因為std::string需要動態內存管理,無法編譯期求值。

只有一個類型為 IiteralType,才能被constexpr修飾。

此處的IiteralType稱為字面量類型,包含五種情況:

  1. void類型(C++14后支持,C++11不允許返回void
  2. 標量類型
  3. 引用類型
  4. 字面類型數組
  5. 類類型,且滿足:
    • 有一個平凡的 constexpr 析構函數
    • 所有非靜態非變體數據成員和基類都是字面類型
    • 滿足以下之一:
      • lambda 類型(C++17后)
      • 至少有一個 constexpr修飾的構造函數,且該構造不是拷貝構造或移動構造
      • 聚合 union 類型, 沒有變體成員 或者 至少有一個非易失性字面類型的變體成員
      • 聚合 非union 類型,且如果有內置匿名聯合成員,該聯合必須滿足上一條

這一大段著實讓人看著頭大了,引入了非常多從未接觸過的定義。但這已經是我簡化過的版本,可參考官網描述:C++ 命名要求: LiteralType (自 C++11 起),官網對這一部分的描述,可以說是非常晦澀。

簡單來說,總共有五種情況滿足IiteralType,其中第五種是針對類類型。

對于類類型,要求滿足三個要求,而第三條要求內部,又需要滿足四個條件之一。

首先解釋部分專有名詞:

  • 字面類型數組:此處專指T arr[n]這種形式,也就是C風格的數組,且數組的元素類型必須是字面類型

  • 非靜態:也就是沒有被static修飾的類成員

  • 非易失性:被volatile修飾的變量稱為易失性變量,非易失性即沒有被volatile修飾

  • 平凡析構函數:一個析構函數被認為是平凡的,當它同時滿足以下所有條件:

    • 隱式定義或默認定義:沒有用戶提供的析構函數定義(即使用= default或完全不聲明析構函數)。
    • 非虛析構函數:析構函數沒有被聲明為virtual虛函數。
    • 所有基類和非靜態數據成員都有平凡的析構函數:類的直接基類和所有非靜態數據成員的析構函數也必須是平凡的。
  • 聚合類型:滿足以下要求:

    • 無用戶提供或繼承的構造函數:聚合類型可以有默認構造函數,但必須是編譯器自動生成的,不能有用戶顯式定義的構造函數(除了= default形式顯式要求編譯器生成默認構造函數的情況 )。

    • 無私有或保護的非靜態數據成員:所有非靜態數據成員都是公有的,可以直接訪問。

    • 無虛函數和虛基類:聚合類型不包含虛函數,因為虛函數涉及到運行時多態,會增加類型的復雜性。

    可以說,當一個類屬于聚合類型,幾乎就退化到了C語言的struct的狀態,不含復雜的構造,內存模型簡單,可以在編譯期完成求值。

  • 變體成員

    引入一個概念,類聯合體類,是聯合體union 或 至少有一個匿名聯合體作為成員的非聯合體類。

    簡而言之,就是一個聯合體union本身算作類聯合體類,或者當一個類內部包含了匿名union,也叫做類聯合體類

    例如:

    union my_union
    {int x;int y;
    };class my_class
    {union{int a;int b;} _u;
    };
    

    代碼中的聯合體my_union和類my_class都算 類聯合體類。對于my_class,他內部有一個成員_u,是一個匿名聯合體,因為union關鍵字后面沒有聯合體的名稱。

    對于類聯合體類,內部的聯合體的成員,叫做變體成員。即以上的xyab都叫做變體成員。

現在回看之前的IiteralType要求,我做出一定修改:

  1. void類型 (C++14后)
  2. 標量類型
  3. 引用類型
  4. C風格數組,且數組成員都是字面類型
  5. 類類型,且滿足:
    • 有一個平凡的 constexpr 析構函數
    • 所有 不被staticvolatile修飾的成員 和 基類 都是字面類型
    • 滿足以下之一:
      • lambda 類型(C++17后)
      • 至少有一個 constexpr修飾的構造函數,且該構造不是拷貝構造或移動構造
      • 它是聚合類型,且不是類聯合體類
      • 它是聚合類型,且是類聯合體類:聯合體內不存在變體成員,或者至少存在一個不被volatile修飾的變體成員

接下來,我再對部分條目做出一定解釋。

回到 IiteralType 的本質,它就是一個constexpr修飾類型的要求。既然要在編譯期完成計算,那么這個類型要在編譯期就可以確認,以上五條性質就是在要求IiteralType是在編譯期可計算的

首先是C風格數組,它在定義時確定了數組長度,以及每個元素類型,那么編譯期就可以確定它的內存布局。

例如以下 constexpr 是合法的:

constexpr int arr[] = { 1, 2, 3 };

如果要用一個constexpr修飾類類型:

  1. 首先要有一個平凡的析構函數,這個在之前講了,也就是析構函數是默認的,并且不被viture修飾,所有成員和基類也都有平凡的析構。這一步保證了這個類沒有復雜的內部實現,可以迅速銷毀,也反映其內存模型簡單。
  2. 所有的不被staticvolatile修飾的成員 和 基類 都是 IteralType

這兩個條件,基本限制了類的模型不會非常復雜,幾乎不可能存在類似于動態內存管理這樣的操作,在編譯期可能完成求值。

  1. 滿足四個條件之一
  • lambda,其實不是所有lambda都可以,這個不深入講,屬于C++17的特性
  • 至少有一個constexpr修飾的構造,并且這個構造不是拷貝構造或移動構造

這個是下一段內會講到的,constexpr可以修飾函數,那么這個函數就可以在編譯期完成調用得到結果。被constexpr修飾的函數,內部會有很多限制,無法完成太過于復雜的操作。因此當constexpr修飾構造,說明構造不會太復雜,可以在編譯期完成構造函數的調用,那么也就可以在編譯期初始化出對象。

但是這個構造不能是拷貝構造或者移動構造,這其實是一個先有雞還是先有蛋的問題。想一想,如果某個類只有拷貝構造或者移動構造被constexpr修飾。現在在編譯期一個該類型的對象C要完成求值,C的拷貝/移動構造必須傳入另外一個同類型的對象B,但是B從哪里來呢?要么是從一個普通的構造函數,但是剛才說了,普通的構造不被constexpr修飾,無法在編譯期求到值。另外一種就是也通過拷貝或者移動而來,那么B又要再去依賴另外一個同類對象A,以此類推,編譯期根本不可能完成構造對象的任務。因此這個構造不能是拷貝構造或移動構造。

  • 如果這個類型是一個聚合類型,且不是類聯合體類

那么這個類本身就非常簡單,滿足聚合類型就說明內存模型不會太復雜了,在編譯期可以完成求值。

  • 如果這個類型是一個聚合類型,且是類聯合體類,聯合體內不存在變體成員,或者至少存在一個不被volatile修飾的變體成員

也就是說,它是一個union或者類內包含匿名union,此時要考慮變體成員的問題。

第一種是不存在變體成員

例如:

union my_union
{
};class my_class
{union{} _u;
};

my_unionmy_class::_u都不含任何變體成員,那么編譯期對于這兩個內容,完全就不用考慮內存如何分配的問題,因此可以在編譯期完成計算。

第二種是至少存在一個不被volatile修飾的變體成員

例如:

union my_union
{int x;volatile int y; 
};

此處,就算yvolatile修飾,有可能會在后續發生改變。但是x是沒有被修飾的變體成員,這個my_union依然可以被constexpr修飾。

但是以下情況就不行了:

union my_union
{volatile int x;volatile int y;
};

這個類聯合體類內,所有變體成員都被volatile修飾,那么編譯期就算可以確認其值,但是無法保證其后續不會發生改變,不符合constexpr的要求。

沒想到一個小小的constexpr能牽扯到這么多亂七八糟的知識點,也算是在C++龐大的知識圖譜中拓展了一塊未踏足版圖。


函數

constexpr 也可以修飾函數,讓一個函數在編譯期進行計算得到結果。在C++11,這個函數只能包含一個return語句,在C++14及C++17拓展后,允許支持復雜的邏輯以及遞歸。不過遞歸是有層數限制的,不同編譯器取值不同,在256 ~ 2048之間不等。

  • 語法:
constexpr ret_type name(...)
{// 函數體
}

只需要在函數返回值左側加上一個constexpr關鍵字,這個函數就變成了constexpr函數,可以在編譯期進行求值。

例如:

constexpr int fibonacci(int n) 
{if (n <= 0)return 0;else if (n == 1)return 1;elsereturn fibonacci(n - 1) + fibonacci(n - 2);
}int main()
{constexpr int constexpr_ret = fibonacci(5);return 0;
}

這個函數用于在編譯期求出一個斐波那契的第n個元素。函數內部有遞歸,分支語句,當使用一個constexpr變量接受返回值,那么整個函數就會在編譯期進行運算,并得到結果。

只有滿足以下要求,一個函數才會有機會成為constexpr

  1. 返回值和參數都是 IiteralType(字面量類型)
  2. 函數內不能調用其他非 constexpr 函數
  3. 不拋異常

其中IiteralType剛才講過了,在C++11之前,constexpr是不允許返回void類型,也就是必須有返回值的。

但是在剛剛的IiteralType的要求中,第一條就是C++14新增的,void也算IiteralType了,因此C++14后constexpr函數可以沒有返回值。

但是,一個constexpr修飾的函數,不一定在編譯期得到返回值

還記得之前提到,constexpr修飾一個變量,要求初始化這個變量,并且在編譯期就可以拿到值。

int a = 2;
constexpr int b = a + 1;

以上代碼就是錯誤的,因為b依賴了一個運行時求值的a

對于函數也是同理的,函數的參數就算是IteralType,也不能保證函數參數就在編譯期可以求出值,這些參數的實參也必須是constexpr

例如:

constexpr int add(int x, int y)
{return x + y;
}

以下是正確的調用:

constexpr int a = 1;
constexpr int ret1 = add(a, 10);int b = 20;
int ret2 = add(b, b + 10);

ret1的調用中,add的參數a10都是編譯期確定的,調用成功。在ret2的調用中,盡管b是運行時確定的,但是返回值ret2也沒有被constexpr修飾,不要求其在編譯期求值,那么此時就當做一個普通函數在運行時調用。

以下是錯誤的調用:

int a = 1;
constexpr int ret = add(a, 10);

此處a是一個運行時求值的變量,但是ret要求編譯期求值。盡管add確實是被constexpr修飾的函數,函數參數也滿足IteralType,但是實參a編譯期拿不到值,最后代碼就會報錯。


自定義字面量

C++11 引入了用戶自定義字面量,允許程序員為自定義類型或特殊語義賦予類似內置字面量的直觀寫法。通過自定義字面量后綴,可以讓代碼更具可讀性和表達力。

自定義字面量的本質是重載 operator"",即字面量運算符。其語法如下:

返回類型 operator "" _后綴(參數列表)
{// 實現
}
  • _后綴必須以下劃線開頭,且不能包含雙下劃線(__),也不能以下劃線+大寫字母開頭,如 _A,這些都被保留給標準庫使用。
  • 參數類型由字面量的類型決定,常見有:
    • unsigned long long:用于整數字面量
    • long double:用于浮點字面量
    • const char*:用于字符串字面量
    • const char*, std::size_t:字符串字面量 + 長度

例如:

using second = unsigned long long;second operator""_h(unsigned long long h) 
{ return h * 3600; 
}second operator""_m(unsigned long long m) 
{ return m * 60; 
}second operator""_s(unsigned long long s) 
{ return s; 
}void show_time(second s) 
{std::cout << "second: " << s << std::endl;
}int main() 
{show_time(2_h + 30_m + 15_s);
}

通過自定義字面量,2_h30_m15_s 直觀表達了時間單位,避免了數字和單位混淆。

參數匹配與重載規則

自定義字面量的參數類型由字面量本身決定,常見匹配規則如下:

參數列表適用場景示例
(unsigned long long)整數字面量123_后綴
(long double)浮點字面量3.14_后綴
(const char*)字符串字面量"abc"_后綴
(const char*, std::size_t)字符串字面量"abc"_后綴
(char)字符字面量'a'_后綴

首先,對于算數類型unsigned long longdouble,直接數值_后綴即可,對于字符串則需要加雙引號"字符串"_后綴,字符使用單引號'字符'_后綴,這是調用字面量重載的語法。

對于字符串,有兩種函數參數形式,兩者調用的方法是相同的,只是兩個參數的版本,可以operator ""函數體內部拿到字符串的長度,更加方便。

例如:

const char* operator""_x(const char* str)
{ }const char* operator""_x(const char* str, size_t len) 
{ }

兩個_x的后綴重載都是針對字符串類型,但是如果兩個都實現了,優先調用帶len的版本

此外,后綴重載允許拼接字符串,例如:

"123""hello"_x;

這種調用方式是合法的,最后"123hello"作為參數。

如果使用整形,比如123_x,它的行為也比較特殊:

  1. 如果有unsigned long long,優先匹配
  2. 如果沒有前者,整形會轉化為字符串匹配const char*
  3. 如果前兩者都沒有,不會匹配const char*, size_tlong double,字面量報錯

此外,像這種字面量的計算一般不會很復雜,后綴重載常常被聲明為constexpr函數


靜態斷言

C++11 引入了 static_assert,用于在編譯期進行條件檢查。與傳統的C風格 assert不同,static_assert 能在編譯階段捕獲錯誤,提升類型安全和模板編程的健壯性。

在 C++11 之前,常用的靜態斷言方式是利用非法類型或非法表達式強制編譯器報錯。

例如:

#define STATIC_ASSERT(expr) \do { enum { _assert_ = 1 / (expr) }; } while(0)template<class T, class U>
void var_copy(T& a, const U& b) 
{STATIC_ASSERT(sizeof(a) == sizeof(b));memcpy(&a, &b, sizeof(b));
}

以上代碼實現兩個不同類型之間的按字節拷貝。但是拷貝之前要保證兩者類型的字節長度相同。此時使用自己定義的STATIC_ASSERT宏函數,expr表達式返回一個布爾值,如果為true,那么1 / 1合法,斷言通過。但是如果expr返回false,那么1 / 0,發生錯誤,直接終止程序。

這種方式確實可以實現斷言,但是錯誤信息不明確,無法知道具體是哪一個錯誤。

C++11 提供了原生的 static_assert 關鍵字,語法如下:

static_assert(常量表達式, "錯誤信息");
  • 第一個參數必須是編譯期可確定的常量表達式。
  • 第二個參數是自定義的錯誤信息,編譯失敗時會輸出。

示例:

template<class T, class U>
void var_copy(T& a, const U& b) 
{static_assert(sizeof(a) == sizeof(b), "params must have same width.");memcpy(&a, &b, sizeof(b));
}

如果 ab 類型不同,編譯器會在編譯階段報錯,并輸出自定義信息"params must have same width."

相比于C風格的assertstatic_assert可以攜帶錯誤信息,并且可以在編譯期就完成判斷。


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

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

相關文章

【每天一個知識點】多模態信息(Multimodal Information)

常用的多模態信息&#xff08;Multimodal Information&#xff09;指的是來源于多種感知通道/數據類型的內容&#xff0c;這些信息可以被整合處理&#xff0c;以提升理解、推理與生成能力。在人工智能和大模型系統中&#xff0c;典型的多模態信息主要包括以下幾類&#xff1a;?…

iOS 抓包工具精選對比:不同調試需求下的工具適配策略

iOS 抓包痛點始終存在&#xff1a;問題不是“抓不抓”&#xff0c;而是“怎么抓” 很多開發者都遇到過這樣的情況&#xff1a; “接口沒有返回&#xff0c;連日志都沒打出來”“模擬器正常&#xff0c;真機無法請求”“加了 HTTPS 雙向認證&#xff0c;抓不到了”“明明設置了 …

圖像修復:深度學習實現老照片劃痕修復+老照片上色

第一步&#xff1a;介紹 1&#xff09;GLCIC-PyTorch是一個基于PyTorch的開源項目&#xff0c;它實現了“全局和局部一致性圖像修復”方法。該方法由Iizuka等人提出&#xff0c;主要用于圖像修復任務&#xff0c;能夠有效地恢復圖像中被遮擋或損壞的部分。項目使用Python編程語…

css 邊框顏色漸變

border-image: linear-gradient(90deg, rgba(207, 194, 195, 1), rgba(189, 189, 189, 0.2),rgba(207, 194, 195, 1)) 1;

本地 LLM API Python 項目分步指南

分步過程 需要Python 3.9 或更高版本。 安裝 Ollama 并在本地下載 LLM 根據您的操作系統&#xff0c;您可以從其網站下載一個或另一個版本的 Ollama 。下載并啟動后&#xff0c;打開終端并輸入以下命令&#xff1a; ollama run llama3此命令將在本地拉取&#xff08;下載&…

日本的所得稅計算方式

? 【1】所得稅的計算步驟&#xff08;概要&#xff09; 日本的所得稅大致按照以下順序來計算&#xff1a; 1?? 統計收入&#xff08;銷售額、工資等&#xff09; 2?? 扣除必要經費等&#xff0c;得到「所得金額」 3?? 扣除各類「所得控除」&#xff08;所得扣除&#xf…

【langchain4j篇01】:5分鐘上手langchain4j 1.1.0(SpringBoot整合使用)

目錄 一、環境準備 二、創建項目、導入依賴 三、配置 application.yml 四、注入Bean&#xff0c;開箱即用 五、日志觀察 一、環境準備 首先和快速上手 Spring AI 框架一樣的前置條件&#xff1a;先申請一個 apikey &#xff0c;此部分步驟參考&#xff1a;【SpringAI篇01…

js運算符

運算符 jarringslee*賦值運算符 - / 對變量進行賦值的運算符&#xff0c;用于簡化代碼。左邊是容器&#xff0c;右邊是值一元運算符正號 符號- 賦予數據正值、負值自增 自減– 前置和后置&#xff1a;i和i&#xff1a;一般情況下習慣使用后置i&#xff0c;兩者在單獨…

next.js 登錄認證:使用 github 賬號授權登錄。

1. 起因&#xff0c; 目的: 一直是這個報錯。2. 最終效果&#xff0c; 解決問題&#xff0c;能成功登錄、體驗地址&#xff1a;https://next-js-gist-app.vercel.app/代碼地址&#xff1a; https://github.com/buxuele/next-js-gist-app3. 過程: 根本原因: github 的設置&…

深入理解設計模式:原型模式(Prototype Pattern)

在軟件開發中&#xff0c;對象的創建是一個永恒的話題。當我們需要創建大量相似對象&#xff0c;或者對象創建成本較高時&#xff0c;傳統的new操作符可能不是最佳選擇。原型模式&#xff08;Prototype Pattern&#xff09;為我們提供了一種優雅的解決方案——通過克隆現有對象…

Rocky Linux 9 源碼包安裝php8

Rocky Linux 9 源碼包安裝php8大家好&#xff0c;我是星哥&#xff01;今天咱們不聊yum一鍵安裝的“快餐式”部署&#xff0c;來點兒硬核的——源碼編譯安裝PHP 8.3。為什么要折騰源碼&#xff1f;因為它能讓你深度定制PHP功能、啟用最新特性&#xff0c;還能避開系統默認源的版…

Django母嬰商城項目實踐(四)

4、路由規劃與設計 1、概述 介紹 路由稱為 URL(Uniform Resource Locator,統一資源定位符),也稱為 URLconf,對互聯網上得到的資源位置和訪問方式的一種簡潔表示,是互聯網上標準梓源的地址。互聯網上的每個文件都有一個唯一的路由,用于指出網站文件的路由位置,也可以理…

論文閱讀:arxiv 2025 A Survey of Large Language Model Agents for Question Answering

https://arxiv.org/pdf/2503.19213 https://www.doubao.com/chat/12038636966213122 A Survey of Large Language Model Agents for Question Answering 文章目錄速覽論文翻譯面向問答的大型語言模型代理綜述摘要一、引言速覽 這篇文檔主要是對基于大型語言模型&#xff08;…

ONNX 是什么

ONNX 是什么&#xff1f; ONNX&#xff0c;全稱 Open Neural Network Exchange&#xff0c;是微軟和 Facebook&#xff08;現在的 Meta&#xff09;聯合發起的一個開放的神經網絡模型交換格式。簡單理解&#xff1a;ONNX 是一個通用的「AI 模型存檔格式」。用 PyTorch、TensorF…

【Python3】掌握DRF核心裝飾器:提升API開發效率

在 Django REST Framework (DRF) 中&#xff0c;裝飾器&#xff08;Decorators&#xff09;通常用于視圖函數或類視圖&#xff0c;以控制訪問權限、請求方法、認證等行為。以下是 DRF 中常用的裝飾器及其功能說明&#xff1a; 1. api_view 用途: 用于基于函數的視圖&#xff0c…

Datawhale AI 夏令營第一期(機器學習方向)Task2 筆記:用戶新增預測挑戰賽 —— 從業務理解到技術實現

Datawhale AI夏令營第一期&#xff08;機器學習方向&#xff09;Task2筆記&#xff1a;用戶新增預測挑戰賽——從業務理解到技術實現 一、任務核心&#xff1a;業務與技術的“翻譯” 本次Task聚焦“用戶新增預測挑戰賽”的核心邏輯&#xff0c;核心目標是鍛煉“將業務問題轉化為…

【人工智能】華為昇騰NPU-MindIE鏡像制作

本文通過不使用官方鏡像,自己在910b 進行華為mindie的鏡像制作,可離線安裝部署。 硬件:cann 8.0 1. 部署參考文檔: 安裝依賴-安裝開發環境-MindIE安裝指南-MindIE1.0.0開發文檔-昇騰社區 2. 參數說明文檔:https://www.hiascend.com/document/detail/zh/mindie/100/min…

關于我用AI編寫了一個聊天機器人……(番外1)

極大地精簡了1.3.6版本的邏輯。 不會作為正式版發布。 未填充數據。核心結構代碼包含兩個主要部分&#xff1a;數據結構&#xff1a;使用map<string, string>存儲問答對&#xff0c;其中鍵是問題&#xff0c;值是答案主程序流程&#xff1a;初始化預定義的問答對進入無限…

全球鈉離子電池市場研究,市場占有率及市場規模

鈉離子電池是一種新興的儲能技術&#xff0c;利用鈉離子&#xff08;Na?&#xff09;代替鋰離子作為電荷載體&#xff0c;為鋰離子電池提供了一種經濟高效且可持續的替代品。它們的工作原理類似&#xff0c;在充電和放電循環過程中&#xff0c;鈉離子在陽極和陰極之間移動。關…

SwiftUI 全面介紹與使用指南

目錄一、SwiftUI 核心優勢二、基礎組件與布局2.1、基本視圖組件2.2、布局系統2.3、列表與導航三、狀態管理與數據流3.1、狀態管理基礎3.2、數據綁定與共享四、高級功能與技巧4.1、動畫效果4.2、繪圖與自定義形狀4.3、網絡請求與異步數據五、SwiftUI 最佳實踐六、SwiftUI 開發環…