C++模板總結

文章目錄

  • 寫在前面
  • 1. 函數模板
    • 1.1 函數模板的概念
    • 1.2 函數模板的原理
    • 1.3 函數模板的實例化
    • 1.4 函數模板的實例化模板參數的匹配原則
  • 2. 類模板
  • 3. 非類型模板參數
  • 4. 模板的特化
    • 4.1 概念
    • 4.2 函數模板特化
    • 4.3 類模板特化
  • 5. 模板分離編譯
  • 6. 總結

寫在前面

進入C++以后,C++支持了函數重載也就是在同一作用域中可以存在功能類似的同名函數,例如swap函數來完成int,double,char等數據類型的交換。

void swap(int& e1, int& e2)
{int tmp = e1;e1 = e2;e2 = tmp;
}
void swap(double& e1, double& e2)
{double tmp = e1;e1 = e2;e2 = tmp;
}
void swap(char& e1, char& e2)
{char tmp = e1;e1 = e2;e2 = tmp;
}

但是函數重載面臨的問題是:

  1. 重載的函數僅僅是類型不同,功能是類似,所以代碼復用率比較低,而且一旦有新類型出現,就需要用戶自己 增加對應的函數。
  2. 代碼的可維護性比較低,一個出錯可能所有的重載均出錯

如果在C++中,能夠存在這樣一個模具,通過給這個模具中填充不同材料(類型),來獲得不同材料的鑄件(即生成具體類型的代碼)。類似于活字印刷術,模板可以幫助我們快速生成我們所需的代碼。
在這里插入圖片描述

巧的是前人早已將樹栽好,我們只需在此乘涼。
泛型編程:編寫與類型無關的通用代碼,是代碼復用的一種手段。模板是泛型編程的基礎
在這里插入圖片描述

1. 函數模板

1.1 函數模板的概念

  1. 函數模板概念:函數模板代表了一個函數家族,該函數模板與類型無關,在使用時通過傳遞不同的類型參數來實例化不同類型的函數。這種機制使得代碼更加簡潔和通用,減少了重復代碼的編寫
  2. 函數模板格式:定義一個函數模板時,需要使用關鍵字 template或者class(切記:不能使用struct代替class),后跟一個模板參數列表。
    template<typename T1, typename T2,…,typename Tn>
    返回值類型 函數名(參數列表){}

    以下是一個簡單的例子,展示了如何使用模板來創建一個通用的函數模板,它實現了兩個數值的交換:
//template <typename T>
template <class T>
void swap(T& a, T& b) 
{T temp = a;a = b;b = temp;
}

1.2 函數模板的原理

大家都知道,瓦特改良蒸汽機,人類開始了工業革命,解放了生產力。機器生產淘汰掉了很多手工產品。本質是什么,重復的工作交給了機器去完成。有人給出了論調:懶人創造世界。馬云曾經說過:"懶不是傻懶,如果你想少干,就要想出懶的方法。要懶出風格,懶出境界"。而函數模板是一個藍圖,它本身并不是函數,是編譯器根據使用方式產生特定具體類型函數的模具。所以模板就是將本來應該我們做的重復的事情交給了編譯器。

在編譯器編譯階段,對于模板函數的使用,編譯器需要根據傳入的實參類型來推演生成對應類型的函數以供調用。比如:當用double類型使用函數模板時,編譯器通過對實參類型的推演,將T確定為double類型,然后產生一份專門處理double類型的代碼。通過下面例子來理解一下:

#include <iostream>
using namespace std;
//函數模板
template<class T>
void Swap(T& e1, T& e2)
{T tmp = e1;e1 = e2;e2 = tmp;
}int main()
{int a = 10, b = 20;double x = 10, y = 20;Swap(a, b);Swap(x, y);return 0;
}

在這里插入圖片描述
通過匯編代碼再看一下上面的兩次Swap函數調用,也能看出調用的函數不是同一個,因為它們call的地址都不同。
在這里插入圖片描述

1.3 函數模板的實例化

用不同類型的參數使用函數模板時,稱為函數模板的實例化。模板參數實例化分為:隱式實例化和顯示實例化

  1. 隱式實例化:讓編譯器根據實參推演模板參數的實際類型。
    例如上面的Swap(a, b) 和 Swap(x, y),編譯器根據傳遞給模板函數的參數自動推導出模板參數的類型。實際上,在大多數情況下編譯器都能夠推導出模板參數的類型,但在下面這種情況,編譯器推導不出來模板參數的具體類型,導致編譯錯誤:
    在這里插入圖片描述
    這是因為當調用 Add(e1, e2) 時,e1 的類型是 int,而 e2 的類型是 double,這種情況下編譯器無法自動推導出模板參數 T,因為 int 和 double 是不同的類型。
    解決辦法一:自己來強制轉化,使得e1和e2類型相同。
    在這里插入圖片描述
    解決辦法二:顯示實例化,下面就來介紹一下什么是顯示實例化。

  2. 顯示實例化:在函數名后的<>中指定模板參數的實際類型。
    在調用 Add<int> 時,將 e2 轉換為 int 類型。
    在調用 Add<double> 時,將 e1 轉換為 double 類型。
    通過顯式類型轉換,確保傳遞給模板函數的參數類型一致,從而避免編譯錯誤。
    在這里插入圖片描述

1.4 函數模板的實例化模板參數的匹配原則

  1. 一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化為這個非模板函數。
    在這里插入圖片描述
  2. 對于非模板函數和同名函數模板,如果其他條件都相同,在調動時會優先調用非模板函數而不會從該模板產生出一個實例。如果模板可以產生一個具有更好匹配的函數, 那么將選擇模板。
    在這里插入圖片描述
  3. 模板函數不允許自動類型轉換,但普通函數可以進行自動類型轉換。
    在C++中,模板函數不會進行隱式類型轉換來匹配參數類型,而普通函數會進行隱式類型轉換。如果模板函數不能完全匹配參數類型,編譯器將嘗試調用非模板函數,這時可能會發生隱式類型轉換。在這里插入圖片描述

2. 類模板

  1. 類模板的定義格式:
    template<class T1, class T2, …, class Tn>
    class 類模板名
    {
    // 類內成員定義
    };

    這里,typename 是一個關鍵字,用于指定 T 是一個模板參數。你也可以使用 class 關鍵字來代替 typename,它們在這里是等價的。
    在類模板中,如果要在類外定義成員函數,則需要在定義成員函數時提供模板參數列表。這是為了讓編譯器知道這些函數是屬于哪個模板類的實例。下面的例子,展示了如何在類外定義類模板的成員函數:
// 類模板定義
template <class T>
class MyClass 
{
private:T data;
public:MyClass(T d);       // 構造函數聲明void Print();     // 成員函數聲明
};// 在類外定義構造函數
template <class T>
MyClass<T>::MyClass(T d) : data(d) {}// 在類外定義成員函數
template <class T>
void MyClass<T>::Print() 
{cout << data << endl;
}
  1. 類模板的實例化
    類模板實例化與函數模板實例化不同,類模板實例化需要在類模板名字后跟<>,然后將實例化的類型放在<>中即可,類模板名字不是真正的類,而實例化的結果才是真正的類。實例化類模板意味著根據模板定義創建具體的類,這些具體類使用特定的數據類型。
int main()
{MyClass<int> m1;MyClass<double> m1;return 0;
}

3. 非類型模板參數

模板參數分類類型形參與非類型形參
類型形參即:出現在模板參數列表中,跟在class或者typename之類的參數類型名稱。
非類型形參,就是用一個常量作為類(函數)模板的一個參數,在類(函數)模板中可將該參數當成常量來使用。
例如使用非類型形參來定義一個靜態數組:

#include <iostream>
#include <assert.h>using namespace std;
namespace zzb
{template<class T, size_t N = 10>class array{public:T& operator[](size_t index){assert(index >= 0 && index < _size);return _nums[index];}const T& operator[](int index) const{assert(index >= 0 && index < _size);return _nums[index];}size_t size() const{return _size;}size_t empty()const {return 0 == _size;}private:T _nums[N];size_t _size = N;};
}int main()
{zzb::array<int, 10> nums;return 0;
}

ps:浮點數、類對象以及字符串是不允許作為非類型模板參數的,也就說只有整數類型(包括枚舉)可以作為非類型模板參數
在這里插入圖片描述
而且非類型模板參數必須在編譯期確定,這意味著它們的值或大小必須在編譯時就能確定,而不能依賴于運行時的計算或輸入。這樣做是為了在編譯期間能夠生成對應的代碼,以便在程序運行時能夠直接使用這些參數值

4. 模板的特化

4.1 概念

模板的特化是允許我們為特定類型提供定制的實現,通常情況下使用模板可以實現一些與類型無關的代碼,但對于一些特殊類型的可能會得到一些錯誤的結果,需要特殊處理,在這些情況下是非常有用的。
比如:我們定義一個通用的模板函數來進行小于比較。

// 通用模板函數,用于比較兩個值
template <typename T>
bool Less(const T& a, const T& b) 
{return a < b;
}

當我們調用函數模板來比較兩個整數時,發現可以正常比較。
在這里插入圖片描述
當傳參傳過去的是指針時,它是按照指針的大小來比較的,不是按照指針指向的內容來比比較的,不符合我們的預期。
在這里插入圖片描述
可以看到,Less絕對多數情況下都可以正常比較,但是在特殊場景下就得到錯誤的結果。上述示例中,x是小于y的,但是Less內部并沒有比較a和b指向的對象內容,而按照地址的大小比較的,這就無法達到預期而錯誤。此時,就需要對模板進行特化。即:在原模板類的基礎上,針對特殊類型所進行特殊化的實現方式。模板特化中分為函數模板特化與類模板特化。

4.2 函數模板特化

函數模板的特化步驟:
1.必須要先有一個基礎的函數模板,它可以處理大多數情況。

// 通用模板函數,用于比較兩個值
template <typename T>
bool Less(const T& a, const T& b) 
{return a < b;
}

2.關鍵字template后面接一對空的尖括號<>。
3.函數名后跟一對尖括號,尖括號中指定需要特化的類型。
4.函數形參表: 必須要和模板函數的基礎參數類型完全相同,如果不同編譯器可能會報一些奇怪的錯誤。

//函數模板的特化
template <>
bool Less<int*>(const int*& a, const int*& b) 
{return *a < *b;
}

此時傳參再傳過去指針時,它就是按照指針指向的內容來比較的,符合我們的預期。這是因為特化模板在模板實例化時會優先于通用模板
在這里插入圖片描述
我們可以看出上面的特化版本看著特別奇怪 const 寫在int* 后面,因此一般情況下如果函數模板遇到不能處理或者處理有誤的類型,為了實現簡單通常都是將該函數直接給出。

bool Less(const int* a, const int* b)
{return *a < *b;
}

該種實現簡單明了,代碼的可讀性高,容易書寫,因為對于一些參數類型復雜的函數模板,特化時特別給出,因此函數模板不建議特化

4.3 類模板特化

例如有如下專門用來按照小于比較的類模板Less:

template<class T>
struct Less
{bool operator()(const T& e1, const T& e2){return e1 < e2;}
};

調用sort函數排序一個整數數組,發下可以直接排序。
在這里插入圖片描述
調用sort函數排序一個整型指針數組,可以直接排序,但是結果錯誤。
在這里插入圖片描述
同理,這里也需要提供int*的特化版本,而特化分為全特化與偏特化。

1.全特化:將模板參數列表中所有的參數都確定化。

template<>
struct Less<int*>
{bool operator()(int* e1, int* e2){return *e1 < *e2;}
};

上面提供的就是int*的全特化版本,模板參數列表中所有的參數都確定化了,此時運行程序,結果正確。
在這里插入圖片描述
2.偏特化:任何針對模版參數進一步進行條件限制設計的特化版本。
偏特化有以下兩種表現方式

  • 參數更進一步的限制:偏特化并不僅僅是指特化部分參數,而是針對模板參數更進一步的條件限制所設計出來的一個特化版本。
template<class T>
struct Less<T*>
{bool operator()(T* e1, T* e2){return *e1 < *e2;}
};

上面提供的就是T的偏特化版本,對模板參數列表中的參數進行了更進一步的條件限制,不僅能匹配int類型的,是能匹配所有類型的指針。
此時運行程序,結果也是正確的。
在這里插入圖片描述

  • 偏特化的另一種表現方式是部分特化:將模板參數類表中的一部分參數特化。
    例如有如下類模板:
template <typename T1, typename T2>
class MyClass 
{
public:void print(){cout << "MyClass <T1, T2>" << endl;}
};

對上面類進行部分特化:

template <typename T1>
class MyClass<T1, int>
{
public:void print(){cout << "MyClass <T1, int>" << endl;}
};

MyClass<T1, int> 是對第二個模板參數 T2 為 int 的情況進行的特化,在main 函數中,分別調用了基礎模板和部分特化模板,可以看到編譯器根據傳入的類型選擇了合適的模板版本。
在這里插入圖片描述

5. 模板分離編譯

分離編譯:一個程序(項目)由若干個源文件共同實現,而每個源文件單獨編譯生成目標文件,最后將所有目標文件鏈接起來形成單一的可執行文件的過程稱為分離編譯模式。 關于編譯鏈接的相關知識可以看下之前的寫的文章:詳解C語言的編譯與鏈接,這里不再贅述。
而模板分離編譯的分離編譯是將模板的聲明和定義分離到不同的文件中,通常是聲明放到xxx.h,定義放到xxx.cpp。
假如有以下場景,模板的聲明與定義分離開,在頭文件中進行聲明,源文件中完成定義:
1.我們首先在頭文件中聲明函數模板,但不包括具體的實現。

//Swap.h
template<class T>
void Swap(T& e1, T& e2);

2.然后創建一個單獨的實現文件,包含模板的完整定義。


//Swap.cpp
#include "Swap.h"
template<class T>
void Swap(T& e1, T& e2)
{T tmp = e1;e1 = e2;e2 = tmp;
}

3.在使用模板的源文件test.cpp中,包含頭文件Swap.h,然后調用模板Swap來完成兩個數的交換。

//test.cpp
#include <iostream>
#include "Swap.h"
using namespace std;int main()
{int x = 10, y = 20;cout << "交換前 x: " << x << " " << "y: " << y << endl;Swap(x, y);cout << "交換后 x: " << x << " " << "y: " << y << endl;return 0;
}

運行程序,發現報如下錯誤:
在這里插入圖片描述
這是因為,一個C/C++程序要變成一個可執行程序,要經過如下過程:
在這里插入圖片描述
而編譯器對工程中的源文件是單獨編譯的,因此:
在這里插入圖片描述

對于上面的問題有如下兩個解決辦法:
1.在模板定義的位置顯式實例化(不推薦)
在這里插入圖片描述
這種辦法存在一定的弊端,當再有兩個double類型的變量調用函數模板完成交換時,又會報錯。
在這里插入圖片描述
要想解決這個錯誤,就只能在模板定義的地方再去實例化一份Swap<double>的出來。因此每當出現一個新類型去調用這個模板的時候,都需要去模板定義的地方去顯示實例化一份出來。這種顯式實例化方式只適用于我們能預先知道所需類型的情況且這在泛型編程中并不常見,下面來介紹另一種解決方式。
2. 將聲明和定義放到同一個文件 “xxx.hpp” 里面或者xxx.h(推薦)

//Swap.h
template<class T>
void Swap(T& e1, T& e2)
{T tmp = e1;e1 = e2;e2 = tmp;
}

這也就意味著,當在test.cpp中包含Swap.h的以后,在test.cpp中可以找到函數模板的完整定義,因此可以根據需求實例化出任意需要的函數,就不會報鏈接錯誤了。

在這里插入圖片描述

6. 總結

關于模板的優缺點總結如下:
優點:
1.代碼復用:通過模板,可以編寫通用的代碼,而不需要為每個數據類型編寫單獨的代碼,實現了代碼的高效復用。模板的使用加速了開發過程,因為可以更容易地引入新的數據類型,而無需修改大量現有代碼。C++ 標準模板庫(STL)的產生就是模板技術的重要應用之一,提供了大量高效的容器、算法和迭代器,極大地提高了開發效率。
增強代碼的靈活性:
2.泛型編程:模板允許編寫與類型無關的代碼,可以處理不同類型的數據,增強了代碼的通用性和靈活性。
缺陷:
1.代碼膨脹:模板的實例化會導致生成多個實例代碼,可能導致二進制文件變大,尤其是在大型項目中。模板實例化需要更多的編譯時間,特別是當模板被廣泛使用時,編譯時間會顯著增加。
2. 模板編譯錯誤信息復雜:模板編譯錯誤信息通常非常復雜且冗長,不易理解和調試,定位錯誤可能需要更多的時間和經驗。

至此,本片文章就結束了,若本篇內容對您有所幫助,請三連點贊,關注,收藏支持下。

創作不易,白嫖不好,各位的支持和認可,就是我創作的最大動力,我們下篇文章見!

如果本篇博客有任何錯誤,請批評指教,不勝感激 !!!
在這里插入圖片描述

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

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

相關文章

智能小車——初步想法

需要參考輪趣的智能小車自己搭建一臺智能機器人&#xff0c;這里從底層控制開始逐步搭建。 控制模式 之后要自行搭建智能小車&#xff0c;所以將輪趣的底盤代碼進行學習&#xff0c;根據開發手冊先大致過一遍需要的內容。 有做很多個控制方法&#xff0c;包括了手柄、串口、…

MySQL中的JOIN、LEFT JOIN、RIGHT JOIN講解

在 MySQL 中&#xff0c;JOIN 是一種非常強大的功能&#xff0c;它允許你將兩個或多個表中的行結合起來&#xff0c;基于兩個表之間的共同字段。這種操作在數據庫查詢中非常常見&#xff0c;特別是在處理關系型數據庫時。下面我將分別解釋 JOIN、LEFT JOIN&#xff08;也稱為 L…

uin-app微信小程序自定義tabBar底部菜單實現簡單示例(工作筆記)

在微信小程序中實現自定義 tabBar 可以為你的應用提供更加靈活和個性化的底部導航菜單。由于微信小程序的官方 tabBar 配置功能有限&#xff0c;自定義 tabBar 成為了很多開發者實現復雜底部導航的選擇。以下是一個簡單的示例&#xff0c;說明如何在小程序中實現自定義 tabBar。…

Linux下常見壓縮文件tar.xz、tar.bz2、tar.gz的區別和詳解

文章目錄 tar.xz tar.bz2 tar.gz 的區別三種文件的解壓方式tar.xz的解壓三種壓縮文件的創建方式 tar.xz tar.bz2 tar.gz 的區別 這三個文件擴展名都表示壓縮后的檔案文件&#xff0c;但它們使用不同的壓縮算法。 tar.xz: tar 代表 Tape Archive&#xff0c;它是一種將多個文件…

House holder reflections and Givens rotations

House holder reflections and Givens rotations Householder反射和Givens旋轉是兩種常見的線性代數方法&#xff0c;用于將一個矩陣分解為正交矩陣(Q)和上三角矩陣&#xff0c;即QR分解。它們在數值線性代數中非常重要&#xff0c;特別是在求解線性方程組和特征值問題中。以下…

【若依管理系統】注意事項

1.前端字段必填 rules: {sceneName: [{ required: true, message: "場景名稱不能為空", trigger: "blur" }],orderNum: [{ required: true, message: "顯示排序不能為空", trigger: "blur" }], }, 2.IDEA&#xff0c;默認以debug模式…

python | pyvips,一個神奇的 Python 庫

本文來源公眾號“python”&#xff0c;僅用于學術分享&#xff0c;侵權刪&#xff0c;干貨滿滿。 原文鏈接&#xff1a;pyvips&#xff0c;一個神奇的 Python 庫&#xff01; 大家好&#xff0c;今天為大家分享一個神奇的 Python 庫 - pyvips。 Github地址&#xff1a;https…

Agents 要點

一、Agents概念 人類是這個星球上最強大的 Agent。Agent是一個能感知并自主地采取行動的實體&#xff0c;這里的自主性極其關鍵&#xff0c;Agent要能夠實現設定的目標&#xff0c;其中包括具備學習和獲取知識的能力以提高自身性能。 關鍵點&#xff1a;感知環境、自主決策、具…

前端項目筆記經驗-001

做項目有一段時間了&#xff0c;利用下班或者零碎時間的功夫&#xff0c;想分享一些個人心得和感受。與君共勉。 前端應該具備的幾個能力&#xff1a; &#xff08;1&#xff09;準備假數據&#xff08;模擬數據&#xff09;的能力&#xff0c;因為后端有時候接口沒有準備好&…

element plus 實現跨頁面+跨tab欄多選

文章目錄 element plus 層面數據層面 菜鳥好久沒寫博客了&#xff0c;主要是沒遇見什么很難的問題&#xff0c;今天碰見了一個沒有思路的問題&#xff0c;解決后立馬來和大家伙分享了&#xff01; 菜鳥今天要實現一個需求&#xff0c;就是&#xff1a;實現跨頁面跨 tab欄 多選…

力學篤行(四)Qt 線程與信號槽

線程與信號槽 1. 主窗口&#xff08;MainWindow&#xff09;主線程2. 線程2.1 QThread2.2 QtConcurrent::run()2.3 thread 的調用方式 3. 信號槽3.1 connect3.2 元對象系統中注冊自定義數據類型 附錄一 信號槽機制與主線程進行通信示例 1. 主窗口&#xff08;MainWindow&#x…

MySQL聯合索引最左匹配原則

MySQL中的聯合索引(也叫組合索引)遵循最左匹配原則&#xff0c;即在創建聯合索引時&#xff0c;查詢條件必須從索引的最左邊開始&#xff0c;否則索引不會被使用。在聯合索引的情況下&#xff0c;數據是按照索引第一列排序&#xff0c;第一列數據相同時才會按照第二列排序。 例…

CVE-2024-27292:Docassemble任意文件讀取漏洞復現 [附POC]

文章目錄 CVE-2024-27292&#xff1a;Docassemble任意文件讀取漏洞復現 [附POC]0x01 前言0x02 漏洞描述0x03 影響版本0x04 漏洞環境0x05 漏洞復現1.訪問漏洞環境2.構造POC3.復現 0x06 修復建議 CVE-2024-27292&#xff1a;Docassemble任意文件讀取漏洞復現 [附POC] 0x01 前言 …

冒泡排序與其C語言通用連續類型排序代碼

冒泡排序與其C語言通用連續類型排序代碼 冒泡排序冒泡排序為交換排序的一種&#xff1a;動圖展示&#xff1a;冒泡排序的特性總結&#xff1a;冒泡排序排整型數據參考代碼&#xff08;VS2022C語言環境&#xff09;&#xff1a; 冒泡排序C語言通用連續類型排序代碼對比較的方式更…

法律行業守護神:知識庫+AI大模型,解鎖企業知識全周期管理

在法律行業中&#xff0c;搭建一個有效的知識庫并進行企業知識全生命周期管理確實是一項不小的挑戰。法律環境的復雜性和不斷變化的法規要求企業必須持續更新和維護其知識庫&#xff0c;以確保所有信息的準確性和實時性。 這種系統化的信息管理不僅有助于提高律師和法律顧問的…

打卡第9天-----字符串

我在自學的時候,看了卡爾的算法公開課了,有些題目我就照葫蘆畫瓢寫了一遍js代碼,差不多都寫出來了,有暴力解法,有卡爾推薦的思路和方法。話不多說,直接上題上代碼吧: 一、翻轉字符串里的單詞 leetcode題目鏈接:151. 反轉字符串中的單詞 題目描述: 給你一個字符串 s…

5個自動化面試題,助你過關斬將!

面試時&#xff0c;自動化是軟件測試高頻面試內容&#xff0c;通過學習和準備面試題&#xff0c;你會對可能遇到的問題有所準備&#xff0c;從而減輕面試時的緊張感&#xff0c;讓你在面試中穩操勝券&#xff01; 今天&#xff0c;分享一些在面試中可能會遇到的自動化測試面試…

軟件架構之測評方法

軟件架構之測評方法 第 11 章&#xff1a;測試評審方法11.1 測試方法11.1.1 軟件測試階段11.1.2 白盒測試和黑盒測試11.1.3 缺陷的分類和級別11.1.4 調試 11.2 評審方法11.3 驗證與確認11.4 測試自動化11.5 面向對象的測試 第 11 章&#xff1a;測試評審方法 軟件測試與評審是…

大學生暑假“三下鄉”社會實踐工作新聞投稿指南請查收!

近年來&#xff0c;大學生暑期“三下鄉”社會實踐工作方興未艾&#xff0c;越來越多的大學生通過參與“三下鄉”實踐工作&#xff0c;走出校園&#xff0c;深入基層&#xff0c;體驗農村生活&#xff0c;服務農民&#xff0c;促進農村經濟社會發展&#xff0c;實現了理論與實踐…

算能科技,致力于成為全球領先的通用算力供應商

算能致力于成為全球領先的定制算力提供商&#xff0c;專注于RISC-V、TPU處理器等算力產品的研發和推廣應用。公司遵循全面開源開放的生態理念&#xff0c;攜手行業伙伴推動RISC-V高性能通用計算產業落地&#xff1b;打造覆蓋“云、邊、端”的全場景產品矩陣&#xff0c;為數據中…