目錄
5) 兩大數據降維(Dimensionality Reduction)問題:
1)激活函數:https://www.jianshu.com/p/304a87fcef43
1. 機器學習模型
1) 機器學習和深度學習的區別是什麼?
機器學習是人工智能的一個子集,它爲機器提供了無需任何顯式編程就能自動學習和改進的能力。而深度學習是機器學習的一個子集,人工神經網絡能夠做出直觀的決定。
2) 有監督機器學習和無監督機器學習的區別?
在監督學習中,機器在有標記數據的幫助下進行訓練,即,即帶有正確答案標記的數據。而在無監督機器學習中,模型是通過自身發現信息來學習的。與有監督學習模型相比,無監督學習模型更適合於執行困難的處理任務。
示例:有監督學習:kNN, SVM,BP,RF,GBDT,LR,;無監督學習:k-means
3) k -means和KNN是什麼?
K-means是一種用於聚類問題處理的無監督算法,KNN或K近鄰是一種用於迴歸和分類處理的有監督算法。
4) 當前的「三大」最常見的機器學習任務:
迴歸(Regression):迴歸是一種用於連續型數值變量預測和建模的監督學習算法,特徵是具有數值型目標變量的標註數據集,即一個用以監督算法的觀察樣本,都有一個數值型真值。
分類(Classification):分類是一種用於分類變量建模及預測的監督學習算法,正如你所見,許多回歸算法都有其對應的分類形式,分類算法往往適用於類別(或其可能性)的預測,而非數值。
聚類(Clustering):聚類是基於數據內部結構來尋找樣本自然族羣(集羣)的無監督學習任務,由於聚類屬於無監督學習,也就不會輸出“正確的答案”,評價結果時往往要用到數據可視化。如果你需要“正確的答案”,亦即訓練集中存在預標註的集羣,那麼用分類算法會更加合適。
分類與迴歸區別:這兩個概念都是監督機器學習技術的一個重要方面。通過分類,將輸出劃分爲不同的類別進行預測。而回歸模型通常用來找出預測與變量之間的關係。分類和迴歸的一個關鍵區別是前者的輸出變量是離散的,而後者是連續的。
5) 兩大數據降維(Dimensionality Reduction)問題:
在機器學習領域,“維度(Dimensionality)”通常指數據集中的特徵數量(即輸入變量的個數)。
當特徵的個數特別大的時候(相對於數據集中觀測樣本的數量來說),訓練出一個有效的模型,對算法要求就會特別高(即,用現有的算法訓練出一個有效的模型特別困難)。這就是所謂的“維度災難(Curse of Dimensionality)”,特別是對依賴於距離計算的聚類算法而言。
特徵選取(Feature Selection):特徵選取是從你的數據集中過濾掉不相關或冗餘的特徵。
特徵提取(Feature Extraction):在原特徵集的基礎上重新構造出一些(一個或多個)全新的特徵。
特徵選取與特徵提取的關鍵區別在於:特徵選取是從原特徵集中選取一個子特徵集,而特稱提取則是在原特徵集的基礎上重新構造出一些(一個或多個)全新的特徵。
6)過擬合和欠擬合:
避免過擬合方法:保持模型簡單,第二種方法是使用交叉驗證技術,第三種方法是使用正則化技術,例如LASSO。
7)正則化
正則化是針對過擬合而提出的,以爲在求解模型最優的是一般優化最小的經驗風險,現在在該經驗風險上加入模型複雜度這一項(正則化項是模型參數向量的範數),並使用一個rate比率來權衡模型複雜度與以往經驗風險的權重,如果模型複雜度越高,結構化的經驗風險會越大,現在的目標就變爲了結構經驗風險的最優化,可以防止模型訓練過度複雜,有效的降低過擬合的風險。奧卡姆剃刀原理,能夠很好的解釋已知數據並且十分簡單纔是最好的模型。
使用L1L2正則化,爲什麼可以降低模型的複雜度?模型越複雜,越容易過擬合,這大家都知道,加上L1正則化給了模型的拉普拉斯先驗,加上L2正則化給了模型的高斯先驗。從參數的角度來看,L1得到稀疏解,去掉一部分特徵降低模型複雜度。L2得到較小的參數,如果參數很大,樣本稍微變動一點,值就有很大偏差,這當然不是我們想看到的,相當於降低每個特徵的權重。
8) 邏輯迴歸:
得不到非線性關係,實際問題不能完全用線性關係擬合。
-
2. 深度學習
1)激活函數:https://www.jianshu.com/p/304a87fcef43
Sigmod:=1/(1+e^-x)
優點:輸出值0-1(很重大的優點);其餘的和其他衆多激活函數比起來,感覺沒有什麼優點,方便入門理解
缺點:容易梯度消失;x的可變值區域太小,極其容易陷入級值的狀況(-0.9~0.9);指數exp計算複雜。
Tanh: =(e^x – e^-x)/(e^x + e^-x)
優點:和sigmod比起來,是零均值化處理。(零均值化可以加快模型的收斂);
缺點:和sigmod一樣的缺點
Relu: =max(0,x)
優點:計算複雜度低(只有一個if>0判斷,大於0則激活值爲1),部分區域線性遞增,沒有冪運算與指數運算;
缺點:x小於0時無法產生激活值;訓練到後期可能權重參數更新太大
如何選擇激活函數?不要sigmod,
2)梯度消失,梯度爆炸:
當網絡層數過多時,前面層由於求導過程乘積運算,出現weight與bias變得異常大與異常小的情況
3. 常見算法及程序
1)快排
package com.nrsc.sort;
public class QuickSort {
public static void main(String[] args) {
int[] arr = { 49, 38, 65, 97, 23, 22, 76, 1, 5, 8, 2, 0, -1, 22 };
quickSort(arr, 0, arr.length - 1);
System.out.println("排序後:");
for (int i : arr) {
System.out.println(i);
}
}
private static void quickSort(int[] arr, int low, int high) {
if (low < high) {
// 找尋基準數據的正確索引
int index = getIndex(arr, low, high);
// 進行迭代對index之前和之後的數組進行相同的操作使整個數組變成有序
quickSort(arr, 0, index - 1);
quickSort(arr, index + 1, high);
}
}
private static int getIndex(int[] arr, int low, int high) {
// 基準數據
int tmp = arr[low];
while (low < high) {
// 當隊尾的元素大於等於基準數據時,向前挪動high指針
while (low < high && arr[high] >= tmp) {
high--;
}
// 如果隊尾元素小於tmp了,需要將其賦值給low
arr[low] = arr[high];
// 當隊首元素小於等於tmp時,向前挪動low指針
while (low < high && arr[low] <= tmp) {
low++;
}
// 當隊首元素大於tmp時,需要將其賦值給high
arr[high] = arr[low];
}
// 跳出循環時low和high相等,此時的low或high就是tmp的正確索引位置
// 由原理部分可以很清楚的知道low位置的值並不是tmp,所以需要將tmp賦值給arr[low]
arr[low] = tmp;
return low; // 返回tmp的正確位置
}
}
2) 文件創建、讀取
文件的創建,寫入,讀取
public void fileOperate(String path,String filename) throws IOException{
//文件創建
File filepath=new File(path);
if(!filepath.exists()){
filepath.mkdir();
}
File file=new File(path+"/"+filename);
if(!file.exists()){
file.createNewFile();
}
//文件寫入
FileOutputStream out=new FileOutputStream(file,true);
for(int i=0;i<10000;i++){
StringBuffer sb=new StringBuffer();
sb.append(i.toString());
out.write(sb.toString().getBytes("utf-8"));
}
out.close();
//文件讀取:
FileInputStream fis=new FileInputStream(file);
byte[] buf = new byte[1024];
StringBuffer sb=new StringBuffer();
while((fis.read(buf))!=-1)...{
sb.append(new String(buf));
buf=new byte[1024];//重新生成,避免和上次讀取的數據重複
}
system.printIn.out(sb.toString());
}
3)單例模式
public class SingletonDemo {
private static SingletonDemo instance; //對象
private SingletonDemo(){} //構造函數
public static synchronized SingletonDemo getInstance(){ // getInstance()方法
if (instance == null) {
instance = new SingletonDemo1();
}
return instance;
}
}
靜態內部類:
public class SingletonDemo5 {
private static class SingletonHolder{
private static final SingletonDemo5 instance = new SingletonDemo5();//對象放在內部類裏,Singleton類被裝載了,instance不一定被初始化,延遲加載
}
private SingletonDemo5(){}
public static final SingletonDemo5 getInsatance(){
return SingletonHolder.instance;
}
}
4)冒泡排序
public void bubbleSort(Integer[] arr, int n) {
if (n <= 1) return; //如果只有一個元素就不用排序了
for (int i = 0; i < n; ++i) {
// 提前退出冒泡循環的標誌位,即一次比較中沒有交換任何元素,這個數組就已經是有序的了
boolean flag = false;
for (int j = 0; j < n - i - 1; ++j) { //此處你可能會疑問的j<n-i-1,因爲冒泡是把每輪循環中較大的數飄到後面,
// 數組下標又是從0開始的,i下標後面已經排序的個數就得多減1,總結就是i增多少,j的循環位置減多少
if (arr[j] > arr[j + 1]) { //即這兩個相鄰的數是逆序的,交換
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = true;
}
}
if (!flag) break;//沒有數據交換,數組已經有序,退出排序
}
}
4. 鏈表
鏈表是一種動態的數據結構,因爲在創建鏈表時,我們不需要知道鏈表的長度,當插入一個結點時,只需要爲該結點分配內存,然後調整指針的指向來確保新結點被連接到鏈表中。所以,它不像數組,內存是一次性分配完畢的,而是每添加一個結點分配一次內存。正是因爲這點,所以它沒有閒置的內存,比起數組,空間效率更高。
基本操作
創建節點
struct Node
{
int a; //數據域
struct Node* next; //指針域(指向節點的指針)
};
定義鏈表頭尾指針
struct Node* head= NULL;
struct Node* end = NULL;
創建鏈表:
void AddListTill(int a )
{
//創建一個節點
struct Node* temp=(struct Node*)malloc(sizeof(struct Node)); //此處注意強制類型轉換
//節點數據進行賦值
temp->a=a;
temp->next=NULL;
//連接分兩種情況1.一個節點都沒有2.已經有節點了,添加到尾巴上
if(NULL==head)
{
head=temp;
}
else
{
end->next=temp; //尾結點應該始終指向最後一個
}
end=temp; //尾結點應該始終指向最後一個
}
遍歷鏈表
void ScanList()
{
struct Node *temp =head; //定義一個臨時變量來指向頭
while (temp !=NULL)
{
printf("%d\n",temp->a);
temp = temp->next; //temp指向下一個的地址 即實現++操作
}
}
5. 常見問題
1)http轉發和重定向
- 語句寫法:轉發forward,重定向sendRedirect;
- 請求次數:轉發是一次請求,重定向是2次請求;
- C/S: 轉發是服務器行爲,重定向是客戶端行爲;
- 地址欄是否改變:轉發後,地址欄顯示的信息不改變,而重定向後,是開始了一個新的Http請求,因此地址欄是redirect後的地址。
詳細:轉發是服務器內部重定向,程序收到請求後重新定向到另一個程序,客戶機並不知道;重定向則是服務器收到請求後發送一個狀態頭給客戶,客戶將再請求一次,這裏多了兩次網絡通信的來往。
2)重寫和重載
方法重寫(overriding): 也叫子類的方法覆蓋父類的方法,要求返回值、方法名和參數都相同。子類異常不能超出父類異常;子類訪問級別不能低於父類訪問級別。
方法重載(overloading): 重載是在同一個類中的兩個或兩個以上的方法,擁有相同的方法名,但是參數卻不相同,方法體也不相同,最常見的重載的例子就是類的構造函數。
3)Final finally finalize
- final
final修飾類,說明這個類不能被繼承,是以個頂級類。
final修飾變量,說明這個變量是常量。
final修飾方法,表示這個方法不能被重寫,不過可以重載final方法。
2. finally
finally是關鍵字,在異常處理中,try子句中執行需要運行的內容,catch子句用於捕獲異常,finally子句表示不管是否發生異常,都會執行。finally可有可無。但是try…catch必須成對出現。
3. finalize()
finalize()是Object類的方法,Java 技術允許使用 finalize()方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象進行調用。finalize()方法是在垃圾收集器刪除對象之前對這個對象調用的子類覆蓋 complete() 方法以整理系統資源或者執行其他清理操作。
4)String stringbuffer
StringBuffer長度和內容可變,String內容和長度不可變。如果使用StringBuffer做字符串的拼接,不會浪費太多的資源。
(1)String是內容不可變的,而StringBuffer、StringBuilder都是內容可變的。
(2)StringBuffer是同步的,數據安全的,但是效率低;StringBuilder是不同步的,數據不安全,效率高。一般情況使用stringbuilder。
5)List set map
Collection是最基本的集合接口,聲明瞭適用於JAVA集合的通用方法。Set 和List 都繼承了Conllection,而Map不是繼承自Collection接口。Collection、List、Set、Map都是接口,不能實例化。繼承自它們的 ArrayList, Vector, HashTable, HashMap是具象class,這些纔可被實例化。
1)Set: 不排序,沒有重複對象。 Set接口主要實現了兩個實現類:
HashSet: HashSet類按照哈希算法來存取集合中的對象,存取速度比較快。
TreeSet:TreeSet類實現了SortedSet接口,能夠對集合中的對象進行排序。
2)List:線性方式存儲,元素可重複。List接口主要實現類包括:
ArrayList() : 代表長度可以改變的數組。可以對元素進行隨機的訪問,向ArrayList()中插入與刪除元素的速度慢。
LinkedList(): 在實現中採用鏈表數據結構。插入和刪除速度快,訪問速度慢。
Vector:變長數組算法
Vector和HashTable是線程同步的(synchronized)。性能上ArrayList和HashMap分別比Vector和Hashtable要好。
3) Map: 是一種把鍵對象和值對象映射的集合,Map沒有繼承於Collection接口。
HashMap:線程不安全,高效,支持null;
HashTable:線程同步安全,低效,不支持null;
TreeMap
6)數據庫事務死鎖
數據庫是一個多用戶使用的共享資源,當多個用戶併發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的情況。
- 事務之間對資源訪問順序的交替
出現原因:
一個用戶A 訪問表A(鎖住了表A),然後又訪問表B;另一個用戶B 訪問表B(鎖住了表B,然後企圖訪問表A;這時用戶A由於用戶B已經鎖住表B,它必須等待用戶B釋放表B才能繼續,同樣用戶B要等用戶A釋放表A才能繼續,這就死鎖就產生了。
解決方法: 這種死鎖比較常見,是由於程序的BUG產生的,除了調整程序的邏輯沒有其它的辦法。仔細分析程序的邏輯,對於數據庫的多表操作時,儘量按照相同的順序進行處理,儘量避免同時鎖定兩個資源,如操作A和B兩張表時,總是按先A後B的順序處理, 必須同時鎖定兩個資源時,要保證在任何時刻都應該按照相同的順序來鎖定資源。
- 併發修改同一記錄
出現原因:
用戶A查詢一條紀錄,然後修改該條紀錄;這時用戶B修改該條紀錄,這時用戶A的事務裏鎖的性質由查詢的共享鎖企圖上升到獨佔鎖,而用戶B裏的獨佔鎖由於A有共享鎖存在所以必須等A釋放掉共享鎖,而A由於B的獨佔鎖而無法上升的獨佔鎖也就不可能釋放共享鎖,於是出現了死鎖。這種死鎖由於比較隱蔽,但在稍大點的項目中經常發生。
解決方法:
a. 使用樂觀鎖進行控制。樂觀鎖大多是基於數據版本(Version)記錄機制實現。即爲數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是通過爲數據庫表增加一個“version”字段來實現。讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認爲是過期數據。樂觀鎖機制避免了長事務中的數據庫加鎖開銷(用戶A和用戶B操作過程中,都沒有對數據庫數據加鎖),大大提升了大併發量下的系統整體性能表現。Hibernate 在其數據訪問引擎中內置了樂觀鎖實現。需要注意的是,由於樂觀鎖機制是在我們的系統中實現,來自外部系統的用戶更新操作不受我們系統的控制,因此可能會造成髒數據被更新到數據庫中。
b. 使用悲觀鎖進行控制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,如Oracle的Select … for update語句,以保證操作最大程度的獨佔性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。如一個金融系統,當某個操作員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶賬戶餘額),如果採用悲觀鎖機制,也就意味着整個操作過程中(從操作員讀出數據、開始修改直至提交修改結果的全過程,甚至還包括操作員中途去煮咖啡的時間),數據庫記錄始終處於加鎖狀態,可以想見,如果面對成百上千個併發,這樣的情況將導致災難性的後果。所以,採用悲觀鎖進行控制時一定要考慮清楚。
c. SqlServer可支持更新鎖
爲解決死鎖,SqlServer引入更新鎖,它有如下特徵:
(1) 加鎖的條件:當一個事務執行update語句時,數據庫系統會先爲事務分配一把更新鎖。
(2) 解鎖的條件:當讀取數據完畢,執行更新操作時,會把更新鎖升級爲獨佔鎖。
(3) 與其他鎖的兼容性:更新鎖與共享鎖是兼容的,也就是說,一個資源可以同時放置更新鎖和共享鎖,但是最多放置一把更新鎖。這樣,當多個事務更新相同的數據時,只有一個事務能獲得更新鎖,然後再把更新鎖升級爲獨佔鎖,其他事務必須等到前一個事務結束後,才能獲取得更新鎖,這就避免了死鎖。
(4) 併發性能:允許多個事務同時讀鎖定的資源,但不允許其他事務修改它
3) 索引不當導致全表掃描
出現原因:
如果在事務中執行了一條不滿足條件的語句,執行全表掃描,把行級鎖上升爲表級鎖,多個這樣的事務執行後,就很容易產生死鎖和阻塞。類似的情況還有當表中的數據量非常龐大而索引建的過少或不合適的時候,使得經常發生全表掃描,最終應用系統會越來越慢,最終發生阻塞或死鎖。
解決方法:
SQL語句中不要使用太複雜的關聯多表的查詢;使用“執行計劃”對SQL語句進行分析,對於有全表掃描的SQL語句,建立相應的索引進行優化。
4個必要條件:
1)互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程佔用。如果此時還有其它進程請求資源,則請求者只能等待,直至佔有資源的進程用畢釋放。
2)請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程佔有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
3)不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。
4)環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0,P1,P2,···,Pn}中的P0正在等待一個P1佔用的資源;P1正在等待P2佔用的資源,……,Pn正在等待已被P0佔用的資源。
7)Public private protected
1、public:public表明該數據成員、成員函數是對所有用戶開放的,所有用戶都可以直接進行調用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有財產神聖不可侵犯嘛,即便是子女,朋友,都不可以使用。
3、protected:protected對於子女、朋友來說,就是public的,可以自由使用,沒有任何限制,而對於其他的外部class,protected就變成private。
4. friendly:當前類和同一包的類可公用。
8)事務
- 事務:數據庫事務(特點:一致性)和Spring事務(我講到了hibernate)
數據庫事務:數據庫事務是指作爲單個邏輯工作單元執行的一系列操作(SQL語句)。這些操作要麼全部執行,要麼全部不執行。通過ACID實現數據庫事務模型(四個屬性)
1) 原子性(Atomicity):事務是數據庫的邏輯工作單位,它對數據庫的修改要麼全部執行,要麼全部不執行。
2) 一致性(Consistemcy):事務執行前後,數據庫的狀態都滿足所有的完整性約束。
3) 隔離性(Isolation):併發執行的事務是隔離的,保證多個事務互不影響。如果有兩個事務,運行在相同的時間內,執行相同的功能,事務的隔離性將確保每一事務在系統中認爲只有該事務在使用系統。這種屬性有時稱爲串行化,爲了防止事務操作間的混淆,必須串行化或序列化請求,使得在同一時間僅有一個請求用於同一數據。通過設置數據庫的隔離級別,可以達到不同的隔離效果。
4) 持久性(Durability):一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。
事務運行的三種模式
1)自動提交事務:默認事務管理模式。如果一個語句成功地完成,則提交該語句;如果遇到錯誤,則回滾該語句。
2)顯式事務:以BEGIN TRANSACTION顯式開始,以COMMIT或ROLLBACK顯式結束。
3)隱性事務:當連接以此模式進行操作時,sql將在提交或回滾當前事務後自動啓動新事務。無須描述事務的開始,只需提交或回滾每個事務。它生成連續的事務鏈。
隔離級別:級別越來越高,併發性越來越差,安全性越來越高
讀未提交(read-uncommitted)-》髒讀
讀已提交(read-committed)-》不可重複讀
可重複讀-》幻讀
順序讀
9)JAVA反射機制
簡單說,反射機制值得是程序在運行時能夠獲取自身的信息。在java中,只要給定類的名字,那麼就可以通過反射機制來獲得類的所有信息。
在運行時能夠判斷任意一個對象所屬的類;
在運行時構造任意一個類的對象
在運行時判斷任意一個類所具有的成員變量和方法
在運行時調用任一對象的方法
在運行時創建新類對象
哪裏用到反射機制:
Class.forName('com.MySQL.jdbc.Driver.class').newInstance();那個時候只知道生成驅動對象實例,後來才知道,這就是反射,現在很多框架都用到反射機制,hibernate,struts都是用反射機制實現的。採用反射機制的話,開發時,新增或更改功能時,它就可以不用卸載,只需要在運行時才動態的創建和編譯,就可以實現該功能。
10) Get和post
http的不同方法:
1. 傳參方式:GET使用URL或Cookie傳參。而POST將數據放在BODY中。
2. 長度:GET的URL的長度會有長度上的限制, POST的數據則可以非常大。
3. 安全性:GET沒有POST安全,因爲數據在地址欄上可見。
4. 速度:get更快。
5. 用途:get用於搜索排序和篩選(淘寶搜索);post用於修改和寫入數據。
(1)post更安全(不會作爲url的一部分,不會被緩存、保存在服務器日誌、以及瀏覽器瀏覽記錄中)
(2)post發送的數據更大(get有url長度限制)
(3)post能發送更多的數據類型(get只能發送ASCII字符)
(4)post比get慢
(5)post用於修改和寫入數據,get一般用於搜索排序和篩選之類的操作(淘寶,支付寶的搜索查詢都是get提交),目的是資源的獲取,讀取數據
11) 數據庫大文件和圖片存儲
- 把圖片直接以二進制形式存儲在數據庫中
一般數據庫提供一個二進制字段來存儲二進制數據。比如mysql中有個blob字段。oracle數據庫中是blob或bfile類型
2. 圖片存儲在磁盤上,數據庫字段中保存的是圖片的路徑。
12) Drop delete truncate
drop table tb刪除內容和定義,釋放空間。簡單來說就是把整個表去掉.
truncate table tb刪除內容、釋放空間但不刪除定義。只是清空表數據;
delete table tb where 條件 刪除內容不刪除定義,不釋放空間
13)深拷貝 淺拷貝
深拷貝就是拷貝對象本身的副本,而淺拷貝只是拷貝了對象的引用,此時會出現一個對象有被兩個指針所指向。
淺拷貝只是對指針的拷貝,拷貝後兩個指針指向同一個內存空間;
深拷貝不但對指針進行拷貝,而且對指針指向的內容進行拷貝。
經淺拷貝後的指針是指向兩個不同地址的指針。兩個指針指向同一個內存空間,在兩次析構函數後,會造成內存泄漏。所以,在對含有指針成員的對象進行拷貝時,必須要自己定義拷貝構造函數,使拷貝後的對象指針成員有自己的內存空間,即進行深拷貝,這樣就避免了內存泄漏發生。
14)數據庫基本概念
-備份:物理備份(歸檔模式/熱備份,非歸檔模式/冷備份),邏輯備份(對數據庫的導入導出操作)。
-數據恢復:完全恢復(恢復到失敗時),不完全(恢復到失敗前);物理恢復,邏輯恢復。
-鎖:共享鎖(讀鎖),排他鎖(寫鎖)
- 存儲過程:sql+控制流語句
- 觸發器:特殊的存儲過程,不需調用自動執行
- 約束:主鍵約束,外鍵約束(參照約束/參照完整性),唯一約束,非空約束,檢查約束
- 範式:1)第一範式:列不可分割;2)第二範式:不能非主鍵對主鍵部分函數依賴;(否則數據冗餘,更新/插入/刪除異常,通常不使用複合主鍵)3)第三範式:不存在函數傳遞依賴。
- Select category avg(productprice) 平均價格
From productinfo
Group by category
having avg(productprice)>20