C++11新標準

重點

  1. auto 類型推導
  2. 范圍 for 迭代
  3. 初始化列表
  4. 變參模板

新類型
C++11新增了類型 long long 和 unsigned long long,以支持64位(或更寬)的整型;新增了類型 char16_t和 char32_t,以支持 16位和 32 位的字符表示;還新增了“原始”字符串。

常量

nullptr

nullptr 出現的目的是為了替代 NULL。 C 與 C++ 語言中有空指針常量,它們能被隱式轉換成任何指針類型的空指針值,或 C++ 中的任何成員指針類型的空成員指針值。 NULL 由標準庫實現提供,并被定義為實現定義的空指針常量。在 C 中,有些標準庫會把 NULL 定義為 ((void*)0) 而有些將它定義為 0

C++ 不允許直接將 void * 隱式轉換到其他類型,從而 ((void*)0) 不是 NULL 的合法實現。如果標準庫嘗試把 NULL 定義為 ((void*)0),那么下面這句代碼中會出現編譯錯誤:

char *ch = NULL;

沒有了 void * 隱式轉換的 C++ 只好將 NULL 定義為 0。而這依然會產生新的問題,將 NULL 定義成 0 將導致 C++ 中重載特性發生混亂。考慮下面這兩個 foo 函數:

void foo(char*);
void foo(int);

那么 foo(NULL); 這個語句將會去調用 foo(int),從而導致代碼違反直覺。

為了解決這個問題,C++11 引入了 nullptr 關鍵字,專門用來區分空指針、0。而 nullptr 的類型為 nullptr_t,能夠隱式的轉換為任何指針或成員指針的類型,也能和他們進行相等或者不等的比較。

#include <iostream>
#include <type_traits>void foo(char *);
void foo(int);int main() {if (std::is_same<decltype(NULL), decltype(0)>::value)std::cout << "NULL == 0" << std::endl;if (std::is_same<decltype(NULL), decltype((void*)0)>::value)std::cout << "NULL == (void *)0" << std::endl;if (std::is_same<decltype(NULL), std::nullptr_t>::value)std::cout << "NULL == nullptr" << std::endl;foo(0);          // 調用 foo(int)// foo(NULL);    // 該行不能通過編譯foo(nullptr);    // 調用 foo(char*)return 0;
}void foo(char *) {std::cout << "foo(char*) is called" << std::endl;
}
void foo(int i) {std::cout << "foo(int) is called" << std::endl;
}

將輸出:?

foo(int) is called
foo(char*) is called

從輸出中我們可以看出,NULL 不同于 0nullptr。所以,請養成直接使用 nullptr的習慣。

此外,在上面的代碼中,我們使用了 decltypestd::is_same 這兩個屬于現代 C++ 的語法,簡單來說,decltype 用于類型推導,而 std::is_same 用于比較兩個類型是否相同,我們會在后面 decltype 一節中詳細討論。

?constexp

C++ 本身已經具備了常量表達式的概念,比如 1+2, 3*4 這種表達式總是會產生相同的結果并且沒有任何副作用。如果編譯器能夠在編譯時就把這些表達式直接優化并植入到程序運行時,將能增加程序的性能。一個非常明顯的例子就是在數組的定義階段:

#include <iostream>
#define LEN 10int len_foo() {int i = 2;return i;
}
constexpr int len_foo_constexpr() {return 5;
}constexpr int fibonacci(const int n) {return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}int main() {char arr_1[10];                      // 合法char arr_2[LEN];                     // 合法int len = 10;// char arr_3[len];                  // 非法const int len_2 = len + 1;constexpr int len_2_constexpr = 1 + 2 + 3;// char arr_4[len_2];                // 非法char arr_4[len_2_constexpr];         // 合法// char arr_5[len_foo()+5];          // 非法char arr_6[len_foo_constexpr() + 1]; // 合法std::cout << fibonacci(10) << std::endl;// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55std::cout << fibonacci(10) << std::endl;return 0;
}

上面的例子中,char arr_4[len_2] 可能比較令人困惑,因為 len_2 已經被定義為了常量。為什么 char arr_4[len_2] 仍然是非法的呢?這是因為 C++ 標準中數組的長度必須是一個常量表達式,而對于 len_2 而言,這是一個 const 常數,而不是一個常量表達式,因此(即便這種行為在大部分編譯器中都支持,但是)它是一個非法的行為,我們需要使用接下來即將介紹的 C++11 引入的 constexpr 特性來解決這個問題;而對于 arr_5 來說,C++98 之前的編譯器無法得知 len_foo() 在運行期實際上是返回一個常數,這也就導致了非法的產生。

注意,現在大部分編譯器其實都帶有自身編譯優化,很多非法行為在編譯器優化的加持下會變得合法,若需重現編譯報錯的現象需要使用老版本的編譯器。

C++11 提供了 constexpr 讓用戶顯式的聲明函數或對象構造函數在編譯期會成為常量表達式,這個關鍵字明確的告訴編譯器應該去驗證 len_foo 在編譯期就應該是一個常量表達式。?

此外,constexpr 修飾的函數可以使用遞歸:

constexpr int fibonacci(const int n) {return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}

?從 C++14 開始,constexpr 函數可以在內部使用局部變量、循環和分支等簡單語句,例如下面的代碼在 C++11 的標準下是不能夠通過編譯的:

constexpr int fibonacci(const int n) {if(n == 1) return 1;if(n == 2) return 1;return fibonacci(n-1) + fibonacci(n-2);
}

為此,我們可以寫出下面這類簡化的版本來使得函數從 C++11 開始即可用:

constexpr int fibonacci(const int n) {return n == 1 || n == 2 ? 1 : fibonacci(n-1) + fibonacci(n-2);
}

變量及其初始化?

if/switch 變量聲明強化

在傳統 C++ 中,變量的聲明雖然能夠位于任何位置,甚至于 for 語句內能夠聲明一個臨時變量 int,但始終沒有辦法在 ifswitch 語句中聲明一個臨時的變量。例如:

#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {1, 2, 3, 4};// 在 c++17 之前const std::vector<int>::iterator itr = std::find(vec.begin(), vec.end(), 2);if (itr != vec.end()) {*itr = 3;}// 需要重新定義一個新的變量const std::vector<int>::iterator itr2 = std::find(vec.begin(), vec.end(), 3);if (itr2 != vec.end()) {*itr2 = 4;}// 將輸出 1, 4, 3, 4for (std::vector<int>::iterator element = vec.begin(); element != vec.end(); ++element)std::cout << *element << std::endl;
}

在上面的代碼中,我們可以看到 itr 這一變量是定義在整個 main() 的作用域內的,這導致當我們需要再次遍歷整個 std::vector 時,需要重新命名另一個變量。C++17 消除了這一限制,使得我們可以在 if(或 switch)中完成這一操作:

// 將臨時變量放到 if 語句內
if (const std::vector<int>::iterator itr = std::find(vec.begin(), vec.end(), 3);itr != vec.end()) {*itr = 4;
}

初始化列表

初始化是一個非常重要的語言特性,最常見的就是在對象進行初始化時進行使用。
在傳統 C++ 中,不同的對象有著不同的初始化方法,例如普通數組、
POD (Plain Old Data,即沒有構造、析構和虛函數的類或結構體)
類型都可以使用 {} 進行初始化,也就是我們所說的初始化列表。
而對于類對象的初始化,要么需要通過拷貝構造、要么就需要使用 () 進行。
這些不同方法都針對各自對象,不能通用。例如:

#include <iostream>
#include <vector>class Foo {
public:int value_a;int value_b;Foo(int a, int b) : value_a(a), value_b(b) {}
};int main() {// before C++11int arr[3] = {1, 2, 3};Foo foo(1, 2);std::vector<int> vec = {1, 2, 3, 4, 5};std::cout << "arr[0]: " << arr[0] << std::endl;std::cout << "foo:" << foo.value_a << ", " << foo.value_b << std::endl;for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << std::endl;}return 0;
}

為解決這個問題,C++11 首先把初始化列表的概念綁定到類型上,稱其為 std::initializer_list,允許構造函數或其他函數像參數一樣使用初始化列表,這就為類對象的初始化與普通數組和 POD 的初始化方法提供了統一的橋梁,例如:

#include <initializer_list>
#include <vector>
#include <iostream>class MagicFoo {
public:std::vector<int> vec;MagicFoo(std::initializer_list<int> list) {for (std::initializer_list<int>::iterator it = list.begin();it != list.end(); ++it)vec.push_back(*it);}
};
int main() {// after C++11MagicFoo magicFoo = {1, 2, 3, 4, 5};std::cout << "magicFoo: ";for (std::vector<int>::iterator it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) std::cout << *it << std::endl;
}

這種構造函數被叫做初始化列表構造函數,具有這種構造函數的類型將在初始化時被特殊關照。

初始化列表除了用在對象構造上,還能將其作為普通函數的形參,例如:

public:void foo(std::initializer_list<int> list) {for (std::initializer_list<int>::iterator it = list.begin();it != list.end(); ++it) vec.push_back(*it);}magicFoo.foo({6,7,8,9});

其次,C++11 還提供了統一的語法來初始化任意的對象,例如:

Foo foo2 {3, 4};

?結構化綁定

結構化綁定提供了類似其他語言中提供的多返回值的功能。在容器一章中,我們會學到 C++11 新增了 std::tuple 容器用于構造一個元組,進而囊括多個返回值。但缺陷是,C++11/14 并沒有提供一種簡單的方法直接從元組中拿到并定義元組中的元素,盡管我們可以使用 std::tie 對元組進行拆包,但我們依然必須非常清楚這個元組包含多少個對象,各個對象是什么類型,非常麻煩。

C++17 完善了這一設定,給出的結構化綁定可以讓我們寫出這樣的代碼:

#include <iostream>
#include <tuple>std::tuple<int, double, std::string> f() {return std::make_tuple(1, 2.3, "456");
}int main() {auto [x, y, z] = f();std::cout << x << ", " << y << ", " << z << std::endl;return 0;
}

類型推導?

在傳統 C 和 C++ 中,參數的類型都必須明確定義,這其實對我們快速進行編碼沒有任何幫助,尤其是當我們面對一大堆復雜的模板類型時,必須明確的指出變量的類型才能進行后續的編碼,這不僅拖慢我們的開發效率,也讓代碼變得又臭又長。

C++11 引入了 autodecltype 這兩個關鍵字實現了類型推導,讓編譯器來操心變量的類型。這使得 C++ 也具有了和其他現代編程語言一樣,某種意義上提供了無需操心變量類型的使用習慣。

auto

auto 在很早以前就已經進入了 C++,但是他始終作為一個存儲類型的指示符存在,與 register 并存。在傳統 C++ 中,如果一個變量沒有聲明為 register 變量,將自動被視為一個 auto 變量。而隨著 register 被棄用(在 C++17 中作為保留關鍵字,以后使用,目前不具備實際意義),對 auto 的語義變更也就非常自然了。

使用 auto 進行類型推導的一個最為常見而且顯著的例子就是迭代器。你應該在前面的小節里看到了傳統 C++ 中冗長的迭代寫法:

// 在 C++11 之前
// 由于 cbegin() 將返回 vector<int>::const_iterator
// 所以 it 也應該是 vector<int>::const_iterator 類型
for(vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); ++it)

而有了 auto 之后可以:

#include <initializer_list>
#include <vector>
#include <iostream>class MagicFoo {
public:std::vector<int> vec;MagicFoo(std::initializer_list<int> list) {// 從 C++11 起, 使用 auto 關鍵字進行類型推導for (auto it = list.begin(); it != list.end(); ++it) {vec.push_back(*it);}}
};
int main() {MagicFoo magicFoo = {1, 2, 3, 4, 5};std::cout << "magicFoo: ";for (auto it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) {std::cout << *it << ", ";}std::cout << std::endl;return 0;
}

一些其他的常見用法:

auto i = 5;              // i 被推導為 int
auto arr = new auto(10); // arr 被推導為 int *

?從 C++ 14 起,auto 能用于 lambda 表達式中的函數傳參,而 C++ 20 起該功能推廣到了一般的函數。考慮下面的例子:

auto add14 = [](auto x, auto y) -> int {return x+y;
}int add20(auto x, auto y) {return x+y;
}auto i = 5; // type int
auto j = 6; // type int
std::cout << add14(i, j) << std::endl;
std::cout << add20(i, j) << std::endl;

注意auto 還不能用于推導數組類型:

auto auto_arr2[10] = {arr}; // 錯誤, 無法推導數組元素類型2.6.auto.cpp:30:19: error: 'auto_arr2' declared as array of 'auto'
auto auto_arr2[10] = {arr};

decltype

decltype 關鍵字是為了解決 auto 關鍵字只能對變量進行類型推導的缺陷而出現的。它的用法和 typeof 很相似:

decltype(表達式)

有時候,我們可能需要計算某個表達式的類型,例如:

auto x = 1;
auto y = 2;
decltype(x+y) z;

你已經在前面的例子中看到 decltype 用于推斷類型的用法,下面這個例子就是判斷上面的變量 x, y, z 是否是同一類型:

if (std::is_same<decltype(x), int>::value)std::cout << "type x == int" << std::endl;
if (std::is_same<decltype(x), float>::value)std::cout << "type x == float" << std::endl;
if (std::is_same<decltype(x), decltype(z)>::value)std::cout << "type z == type x" << std::endl;

其中,std::is_same<T, U> 用于判斷 TU 這兩個類型是否相等。輸出結果為:

type x == int
type z == type x

你可能會思考, auto 能不能用于推導函數的返回類型呢?還是考慮一個加法函數的例子,在傳統 C++ 中我們必須這么寫:

template<typename R, typename T, typename U>
R add(T x, U y) {return x+y;
}

注意:typename 和 class 在模板參數列表中沒有區別,在 typename 這個關鍵字出現之前,都是使用 class 來定義模板參數的。但在模板中定義有嵌套依賴類型的變量時,需要用 typename 消除歧義

這樣的代碼其實變得很丑陋,因為程序員在使用這個模板函數的時候,必須明確指出返回類型。但事實上我們并不知道 add() 這個函數會做什么樣的操作,以及獲得一個什么樣的返回類型。

在 C++11 中這個問題得到解決。雖然你可能馬上會反應出來使用 decltype 推導 x+y 的類型,寫出這樣的代碼:

decltype(x+y) add(T x, U y)

但事實上這樣的寫法并不能通過編譯。這是因為在編譯器讀到 decltype(x+y) 時,xy 尚未被定義。為了解決這個問題,C++11 還引入了一個叫做尾返回類型(trailing return type),利用 auto 關鍵字將返回類型后置:

template<typename T, typename U>
auto add2(T x, U y) -> decltype(x+y){return x + y;
}

令人欣慰的是從 C++14 開始是可以直接讓普通函數具備返回值推導,因此下面的寫法變得合法:

template<typename T, typename U>
auto add3(T x, U y){return x + y;
}

可以檢查一下類型推導是否正確:

// after c++11
auto w = add2<int, double>(1, 2.0);
if (std::is_same<decltype(w), double>::value) {std::cout << "w is double: ";
}
std::cout << w << std::endl;// after c++14
auto q = add3<double, int>(1.0, 2);
std::cout << "q: " << q << std::endl;

decltype(auto)

decltype(auto) 是 C++14 開始提供的一個略微復雜的用法。

要理解它你需要知道 C++ 中參數轉發的概念,我們會在語言運行時強化一章中詳細介紹,你可以到時再回來看這一小節的內容。

簡單來說,decltype(auto) 主要用于對轉發函數或封裝的返回類型進行推導,它使我們無需顯式的指定 decltype 的參數表達式。考慮看下面的例子,當我們需要對下面兩個函數進行封裝時:

std::string  lookup1();
std::string& lookup2();

在 C++11 中,封裝實現是如下形式:

std::string look_up_a_string_1() {return lookup1();
}
std::string& look_up_a_string_2() {return lookup2();
}

?而有了 decltype(auto),我們可以讓編譯器完成這一件煩人的參數轉發:

decltype(auto) look_up_a_string_1() {return lookup1();
}
decltype(auto) look_up_a_string_2() {return lookup2();
}

尾返回類型推導

你可能會思考, auto 能不能用于推導函數的返回類型呢?還是考慮一個加法函數的例子,在傳統 C++ 中我們必須這么寫:

template<typename R, typename T, typename U>
R add(T x, U y) {return x+y;
}

注意:typename 和 class 在模板參數列表中沒有區別,在 typename 這個關鍵字出現之前,都是使用 class 來定義模板參數的。但在模板中定義有嵌套依賴類型的變量時,需要用 typename 消除歧義

這樣的代碼其實變得很丑陋,因為程序員在使用這個模板函數的時候,必須明確指出返回類型。但事實上我們并不知道 add() 這個函數會做什么樣的操作,以及獲得一個什么樣的返回類型。

在 C++11 中這個問題得到解決。雖然你可能馬上會反應出來使用 decltype 推導 x+y 的類型,寫出這樣的代碼:

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

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

相關文章

SpringAI Prompt提示詞

基本概念 Prompts提示詞 ? 提示詞的是引導AI模型輸出的輸入&#xff0c;提示詞的正確性直接影響模型輸出的。 Message消息 Message 接口封裝了 Prompt 文本內容、一組元數據屬性以及稱為 MessageType 的分類。Spring AI消息API&#xff1a; 其中最重要的就是角色&#xff1a; …

力扣刷題——二分查找

數組是存放在連續內存空間上的相同類型數據的集合數組下標都是從0開始的數組內存空間的地址是連續的正是因為數組在內存空間的地址是連續的&#xff0c;所以我們在刪除或者增添元素的時候&#xff0c;就難免要移動其他元素的地址。 使用二分查找法返回的元素下標可能不是唯一的…

黑群暉NAS部署DeepSeek模型與內網穿透實現本地AI服務

文章目錄 前言1.安裝Container Manager2. 啟動ssh功能3. ssh連接黑群暉4. 安裝Ollama5. 安裝deepseek模型6. 安裝open-webui圖形界面7. 安裝內網穿透7.1 下載cpolar套件7.2 配置群輝虛擬機7.3 配置公網地址小結 7.4 配置固定公網地址 總結 前言 在追求自建網絡存儲方案的極客群…

Rust 學習筆記:處理任意數量的 future

Rust 學習筆記&#xff1a;處理任意數量的 future Rust 學習筆記&#xff1a;處理任意數量的 future競爭的 future將控制權交給運行時構建我們自己的異步抽象 Rust 學習筆記&#xff1a;處理任意數量的 future 當兩個 future 切換到三個 future 時&#xff0c;我們也必須從使用…

2025年TCP洪水攻擊防護實戰全解析:從協議對抗到AI智能防御

一、2025年TCP洪水攻擊的新特征與挑戰 AI驅動的自適應攻擊 攻擊者利用生成式AI動態調整SYN報文特征&#xff08;如載荷內容、發送頻率&#xff09;&#xff0c;使攻擊流量與正常業務流量的差異率低至0.5%&#xff0c;傳統基于規則引擎的防御策略完全失效。 混合協議打擊常態化…

二、集成開發環境(IDE)

上節我們在終端演示了python虛擬環境的用法&#xff0c;但終端不方便代碼編寫和調試&#xff0c;本節介紹兩種常用的python集成開發環境&#xff1a;Pycharm和Jupter Notebook。Pycharm是最流行的Python IDE&#xff0c;下載網址&#xff1a;下載 PyCharm&#xff1a;JetBrains…

芯片電感需求趨勢及選型關鍵因素

隨著AI產業的快速發展&#xff0c;數據中心、AI芯片、服務器等算力基礎設施對于芯片電感等電子元件的要求不斷提升。另一方面&#xff0c;電子產品向高功率密度和小型化方向發展&#xff0c;電源模塊趨于小型化、低電壓、大電流&#xff0c;也對芯片電感提出了小型化、輕量化、…

Vue3+Element Plus表單驗證實戰:從零實現用戶管理

前言 在Vue3項目開發中&#xff0c;表單驗證是保證數據完整性和準確性的重要環節。Element Plus作為Vue3的流行UI組件庫&#xff0c;提供了強大的表單驗證功能。本文將基于一個用戶管理模塊的實戰案例&#xff0c;詳細介紹Vue3中如何使用Element Plus實現完整的表單驗證流程。…

力扣上C語言編程題:合并區間(涉及數組)

一. 簡介 本文記錄力扣網上涉及數組方面的編程題&#xff0c;主要以 C語言實現。 二. 力扣上C語言編程題&#xff1a;合并區間&#xff08;涉及數組&#xff09; 以數組 intervals 表示若干個區間的集合&#xff0c;其中單個區間為 intervals[i] [starti, endi] 。請你合并所…

SEO長尾詞與關鍵詞優化實戰

內容概要 在SEO優化體系中&#xff0c;核心關鍵詞與長尾詞的協同作用直接影響流量獲取效率與用戶觸達精度。本文將從基礎概念切入&#xff0c;系統梳理核心關鍵詞的篩選標準與競爭強度評估方法&#xff0c;并深入探討長尾詞在細分場景下的價值定位。通過分析用戶搜索行為與意圖…

博圖SCL語言教程:靈活加、減計數制作自己的增減計數器(CTUD)

博圖SCL語言教程&#xff1a;使用SCL實現增減計數器(CTUD) 一、什么是增減計數器(CTUD)&#xff1f; 增減計數器&#xff08;Up-Down Counter&#xff09;是PLC編程中的基礎功能塊&#xff0c;具有以下特性&#xff1a; CU (Count Up)&#xff1a;上升沿觸發計數值增加 CD (…

Android 應用被kill問題排查和處理

一、背景 博主有一款應用市場應用,同樣的應用,在Android 10上開啟三個下載正常,在Android 14上開啟下載安裝,很頻繁被kill。首先想到的是,是不是應用內存太高,導致被kill,通過工具分析內存也不高,后面就想到是不是系統本身分配給應用的內存就不高,后來通過排查,確實是和系統的…

從代碼學習深度強化學習 - 多臂老虎機 PyTorch版

文章目錄 前言創建多臂老虎機環境多臂老虎機算法基本框架(基類)1. ε-貪心算法 (Epsilon-Greedy)2. 隨時間衰減的ε-貪婪算法 (Decaying ε-Greedy)3. 上置信界算法 (Upper Confidence Bound, UCB)4. 湯普森采樣算法 (Thompson Sampling)總結前言 歡迎來到“從代碼學習深度強化…

Android學習之Window窗口

Android Window機制學習筆記 在使用Window Flag實現界面全屏功能時&#xff0c;發現自身對Android Window機制缺乏系統認知&#xff0c;因此進行了專項學習與整理。 本文主要參考以下優質資料&#xff1a; Android的Window詳解Android官方Window文檔 Window基本概念 1. Win…

華為云 Flexus+DeepSeek 征文|搭建部署Dify-LLM推理引擎,賦能AI Agent智能體實現動態聯網搜索能力

華為云 Flexus 云服務器 X 實例專門為 AI 應用場景設計。它提供了強大的計算能力&#xff0c;能夠滿足 DeepSeek 模型以及后續搭建 AI Agent 智能體過程中對于數據處理和模型運行的高要求。在網絡方面&#xff0c;具備高速穩定的網絡帶寬&#xff0c;這對于需要頻繁聯網搜索信息…

Python 100個常用函數全面解析

Python 100個常用函數全面解析 1. 類型轉換函數 1.1 int() 將字符串或數字轉換為整數。 # 基本用法 int(123) # 123 int(3.14) # 3# 指定進制轉換 int(1010, 2) # 10 (二進制轉十進制) int(FF, 16) # 255 (十六進制轉十進制)# 臨界值處理 int() # ValueError: …

分享在日常開發中常用的ES6知識點【面試常考】

前言 在日常的業務開發中&#xff0c;可以熟悉運用掌握的知識點快速解決問題很重要。這篇分享JS相關的知識點&#xff0c;主要就是對數據的處理。 注意&#xff1a;本篇分享的知識點&#xff0c;只是起到一個拋磚引玉的作用&#xff0c;詳情的使用和更多的ES6知識點還請參考官…

CHI協議驗證中的異常及邊界驗證

CHI協議驗證中的異常及邊界驗證 針對 CHI 協議的錯誤注入工具、覆蓋率衡量方法及實際項目中的投入平衡 CHI 協議作為多核系統中復雜的緩存一致性協議,驗證其行為需要強大的工具和方法來執行錯誤注入和邊界條件測試,并衡量測試覆蓋率。以下詳細討論常用工具、覆蓋率評估方法及…

技術專欄|LLaMA家族——模型架構

LLaMA的模型架構與GPT相同&#xff0c;采用了Transformer中的因果解碼器結構&#xff0c;并在此基礎上進行了多項關鍵改進&#xff0c;以提升訓練穩定性和模型性能。LLaMA的核心架構如圖 3.14 所示&#xff0c;融合了后續提出的多種優化方法&#xff0c;這些方法也在其他模型&a…

電腦插入多塊移動硬盤后經常出現卡頓和藍屏

當電腦在插入多塊移動硬盤后頻繁出現卡頓和藍屏問題時&#xff0c;可能涉及硬件資源沖突、驅動兼容性、供電不足或系統設置等多方面原因。以下是逐步排查和解決方案&#xff1a; 1. 檢查電源供電問題 問題原因&#xff1a;多塊移動硬盤同時運行可能導致USB接口供電不足&#x…