關鍵字庫函數

關鍵字庫函數

轉自:https://leetcode-cn.com/leetbook/read/cpp-interview-highlights/ej3mx1/

sizeof和strlen的區別

  1. strlen 是頭文件<cstring> 中的函數,sizeof 是 C++ 中的運算符。

  2. strlen 測量的是字符串的實際長度(其源代碼如下),以 \0 結束。而 sizeof 測量的是字符數組的分配大小。

    strlen 源代碼

    size_t strlen(const char *str) {size_t length = 0;while (*str++)++length;return length;
    }
    

    舉例:

    #include <iostream>
    #include <cstring>using namespace std;int main()
    {char arr[10] = "hello";cout << strlen(arr) << endl; // 5cout << sizeof(arr) << endl; // 10return 0;
    }
    
  3. 若字符數組 arr 作為函數的形參,sizeof(arr)arr 被當作字符指針來處理,strlen(arr)arr 依然是字符數組,從下述程序的運行結果中就可以看出。

    #include <iostream>
    #include <cstring>using namespace std;void size_of(char arr[])
    {cout << sizeof(arr) << endl; // warning: 'sizeof' on array function parameter 'arr' will return size of 'char*' .cout << strlen(arr) << endl; 
    }int main()
    {char arr[20] = "hello";size_of(arr); return 0;
    }
    /*
    輸出結果:
    8
    5
    */
    
  4. strlen 本身是庫函數,因此在程序運行過程中,計算長度;而 sizeof 在編譯時,計算長度;

  5. sizeof 的參數可以是類型,也可以是變量;strlen 的參數必須是 char* 類型的變量。

lambda 表達式(匿名函數)的具體應用和使用場景

lambda 表達式的定義形式如下:

[capture list] (parameter list) -> reurn type {function body
}

其中:

  • capture list:捕獲列表,指 lambda 表達式所在函數中定義的局部變量的列表,通常為空,但如果函數體中用到了 lambda 表達式所在函數的局部變量,必須捕獲該變量,即將此變量寫在捕獲列表中。捕獲方式分為:引用捕獲方式 [&]、值捕獲方式 [=]
  • return type、parameter list、function body:分別表示返回值類型、參數列表、函數體,和普通函數一樣。

舉例:

lambda 表達式常搭配排序算法使用。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main()
{vector<int> arr = {3, 4, 76, 12, 54, 90, 34};sort(arr.begin(), arr.end(), [](int a, int b) { return a > b; }); // 降序排序for (auto a : arr){cout << a << " ";}return 0;
}
/*
運行結果:90 76 54 34 12 4 3
*/

explicit 的作用(如何避免編譯器進行隱式類型轉換)

作用:用來聲明類構造函數是顯示調用的,而非隱式調用,可以阻止調用構造函數時進行隱式轉換。只可用于修飾單參構造函數,因為無參構造函數和多參構造函數本身就是顯示調用的,再加上 explicit 關鍵字也沒有什么意義。

隱式轉換:

#include <iostream>
#include <cstring>
using namespace std;class A
{
public:int var;A(int tmp){var = tmp;}
};
int main()
{A ex = 10; // 發生了隱式轉換return 0;
}

上述代碼中,A ex = 10; 在編譯時,進行了隱式轉換,將 10 轉換成 A 類型的對象,然后將該對象賦值給 ex,等同于如下操作:

為了避免隱式轉換,可用 explicit 關鍵字進行聲明:

#include <iostream>
#include <cstring>
using namespace std;class A
{
public:int var;explicit A(int tmp){var = tmp;cout << var << endl;}
};
int main()
{A ex(100);A ex1 = 10; // error: conversion from 'int' to non-scalar type 'A' requestedreturn 0;
}

static關鍵字

C和C++static的區別

  • 在 C 語言中,使用 static 可以定義局部靜態變量、外部靜態變量、靜態函數

  • 在 C++ 中,使用 static 可以定義局部靜態變量、外部靜態變量、靜態函數、靜態成員變量和靜態成員函數。因為 C++ 中有類的概念,靜態成員變量、靜態成員函數都是與類有關的概念。

static的作用

作用:

static 定義靜態變量,靜態函數。

  • 保持變量內容持久:static 作用于局部變量,改變了局部變量的生存周期,使得該變量存在于定義后直到程序運行結束的這段時間。
#include <iostream>
using namespace std;int fun(){static int var = 1; // var 只在第一次進入這個函數的時初始化var += 1;return var;
}int main()
{for(int i = 0; i < 10; ++i)cout << fun() << " "; // 2 3 4 5 6 7 8 9 10 11return 0;
}
  • 隱藏:static 作用于全局變量和函數,改變了全局變量和函數的作用域,使得全局變量和函數只能在定義它的文件中使用,在源文件中不具有全局可見性。(注:普通全局變量和函數具有全局可見性,即其他的源文件也可以使用。)

  • static 作用于類的成員變量和類的成員函數,使得類變量或者類成員函數和類有關,也就是說可以不定義類的對象就可以通過類訪問這些靜態成員。注意:類的靜態成員函數中只能訪問靜態成員變量或者靜態成員函數,不能將靜態成員函數定義成虛函數。

#include<iostream>
using namespace std;class A
{
private:int var;static int s_var; // 靜態成員變量
public:void show(){cout << s_var++ << endl;}static void s_show(){cout << s_var << endl;// cout << var << endl; // error: invalid use of member 'A::a' in static member function. 靜態成員函數不能調用非靜態成員變量。無法使用 this.var// show();  // error: cannot call member function 'void A::show()' without object. 靜態成員函數不能調用非靜態成員函數。無法使用 this.show()}
};
int A::s_var = 1;  // 靜態成員變量在類外進行初始化賦值,默認初始化為 0int main()
{   // cout << A::sa << endl;    // error: 'int A::sa' is private within this contextA ex;ex.show();A::s_show();
}

static在類中使用的注意事項(定義、初始化和使用)

static 靜態成員變量

  1. 靜態成員變量是在類內進行聲明,在類外進行定義和初始化,在類外進行定義和初始化的時候不要出現 static 關鍵字和private、public、protected 訪問規則。

  2. 靜態成員變量相當于類域中的全局變量,被類的所有對象所共享,包括派生類的對象。

  3. 靜態成員變量可以作為成員函數的參數,而普通成員變量不可以。

    #include <iostream>
    using namespace std;class A
    {
    public:static int s_var;int var;void fun1(int i = s_var); // 正確,靜態成員變量可以作為成員函數的參數void fun2(int i = var);   //  error: invalid use of non-static data member 'A::var'
    };
    int main()
    {return 0;
    }
    
  4. 靜態數據成員的類型可以是所屬類的類型,而普通數據成員的類型只能是該類類型的指針或引用。

    #include <iostream>
    using namespace std;class A
    {
    public:static A s_var; // 正確,靜態數據成員A var;          // error: field 'var' has incomplete type 'A'A *p;           // 正確,指針A &var1;        // 正確,引用
    };int main()
    {return 0;
    }
    

static 靜態成員函數:

  1. 靜態成員函數不能調用非靜態成員變量或者非靜態成員函數,因為靜態成員函數沒有 this 指針。靜態成員函數做為類作用域的全局函數。
  2. 靜態成員函數不能聲明成虛函數virtualconst 函數和 volatile 函數。

static 全局變量和普通全局變量的異同

相同點:

  • 存儲方式:普通全局變量和 static 全局變量都是靜態存儲方式。

不同點:

  • 作用域:普通全局變量的作用域是整個源程序,當一個源程序由多個源文件組成時,普通全局變量在各個源文件中都是有效的;靜態全局變量則限制了其作用域,即只在定義該變量的源文件內有效,在同一源程序的其它源文件中不能使用它。由于靜態全局變量的作用域限于一個源文件內,只能為該源文件內的函數公用,因此可以避免在其他源文件中引起錯誤。
  • 初始化:靜態全局變量只初始化一次,防止在其他文件中使用。

const、define宏定義、typedef、inline

const作用及用法

作用

  • const 修飾成員變量,定義成 const 常量,相較于宏常量,可進行類型檢查,節省內存空間,提高了效率。
  • const 修飾函數參數,使得傳遞過來的函數參數的值不能改變。
  • const 修飾成員函數,使得成員函數不能修改任何類型的成員變量(mutable 修飾的變量除外),也不能調用非 const 成員函數,因為非 const 成員函數可能會修改成員變量。

在類中的用法

const 成員變量:

  • const 成員變量只能在類內聲明、定義,在構造函數初始化列表中初始化。
  • const 成員變量只在某個對象的生存周期內是常量,對于整個類而言卻是可變的,因為類可以創建多個對象,不同類的 const 成員變量的值是不同的。因此不能在類的聲明中初始化 const 成員變量,類的對象還沒有創建,編譯器不知道他的值。

const 成員函數

  1. 不能修改成員變量的值,除非有 mutable 修飾;只能訪問成員變量。

  2. 不能調用非常量成員函數,以防修改成員變量的值。

#include <iostream>
using namespace std;class A
{
public:int var;A(int tmp) : var(tmp) {}void c_fun(int tmp) const // const 成員函數{var = tmp; // error: assignment of member 'A::var' in read-only object. 在 const 成員函數中,不能修改任何類成員變量。		fun(tmp); // error: passing 'const A' as 'this' argument discards qualifiers. const 成員函數不能調用非 const 成員函數,因為非 const 成員函數可能會修改成員變量。}void fun(int tmp){var = tmp;}
};int main()
{return 0;
}

define和const的區別

區別:

  • 編譯階段:define 是在編譯預處理階段進行替換,const 是在編譯階段確定其值。
  • 安全性:define 定義的宏常量沒有數據類型,只是進行簡單的替換,不會進行類型安全的檢查;const 定義的常量是有類型的,是要進行判斷的,可以避免一些低級的錯誤。
  • 內存占用:define 定義的宏常量,在程序中使用多少次就會進行多少次替換,內存中有多個備份,占用的是代碼段的空間;const 定義的常量占用靜態存儲區的空間,程序運行過程中只有一份。
  • 調試:define 定義的宏常量不能調試,因為在預編譯階段就已經進行替換了;const 定義的常量可以進行調試。

const 的優點:

  • 有數據類型,在定義式可進行安全性檢查。
  • 可調式。
  • 占用較少的空間。

define和typedef的區別

  • 原理:#define 作為預處理指令,在編譯預處理時進行替換操作,不作正確性檢查,只有在編譯已被展開的源程序時才會發現可能的錯誤并報錯。typedef 是關鍵字,在編譯時處理,有類型檢查功能,用來給一個已經存在的類型一個別名,但不能在一個函數定義里面使用 typedef

  • 功能:typedef 用來定義類型的別名,方便使用。#define 不僅可以為類型取別名,還可以定義常量、變量、編譯開關等。

  • 作用域:#define 沒有作用域的限制,只要是之前預定義過的宏,在以后的程序中都可以使用,而 typedef 有自己的作用域。

  • 指針的操作:typedef#define 在處理指針時不完全一樣

#include <iostream>
#define INTPTR1 int *
typedef int * INTPTR2;using namespace std;int main()
{INTPTR1 p1, p2; // p1: int *; p2: intINTPTR2 p3, p4; // p3: int *; p4: int *int var = 1;const INTPTR1 p5 = &var; // 相當于 const int * p5; 常量指針,即不可以通過 p5 去修改 p5 指向的內容,但是 p5 可以指向其他內容。const INTPTR2 p6 = &var; // 相當于 int * const p6; 指針常量,不可使 p6 再指向其他內容。return 0;
}

用宏實現比大小

#include <iostream>
#define MAX(X, Y) ((X)>(Y)?(X):(Y))
#define MIN(X, Y) ((X)<(Y)?(X):(Y))
using namespace std;int main ()
{int var1 = 10, var2 = 100;cout << MAX(var1, var2) << endl;cout << MIN(var1, var2) << endl;return 0;
}
/*
程序運行結果:
100
10
*/

inline作用及使用方法

作用

inline 是一個關鍵字,可以用于定義內聯函數。內聯函數,像普通函數一樣被調用,但是在調用時并不通過函數調用的機制而是直接在調用點處展開,這樣可以大大減少由函數調用帶來的開銷,從而提高程序的運行效率。

使用方法

  1. 類內定義成員函數默認是內聯函數

    在類內定義成員函數,可以不用在函數頭部加 inline 關鍵字,因為編譯器會自動將類內定義的函數(構造函數、析構函數、普通成員函數等)聲明為內聯函數,代碼如下:

    #include <iostream>
    using namespace std;class A{
    public:int var;A(int tmp){ var = tmp;}    void fun(){ cout << var << endl;}
    };int main()
    {    return 0;
    }
    
  2. 類外定義成員函數,若想定義為內聯函數,需用關鍵字聲明

    當在類內聲明函數,在類外定義函數時,如果想將該函數定義為內聯函數,則可以在類內聲明時不加 inline 關鍵字,而在類外定義函數時加上 inline 關鍵字。

    #include <iostream>
    using namespace std;class A{
    public:int var;A(int tmp){ var = tmp;}    void fun();
    };inline void A::fun(){cout << var << endl;
    }int main()
    {    return 0;
    }
    

    另外,可以在聲明函數和定義函數的同時加上 inline;也可以只在函數聲明時加 inline,而定義函數時不加 inline。只要確保在調用該函數之前把 inline 的信息告知編譯器即可。

inline函數工作原理

  • 內聯函數不是在調用時發生控制轉移關系,而是在編譯階段將函數體嵌入到每一個調用該函數的語句塊中,編譯器會將程序中出現內聯函數的調用表達式用內聯函數的函數體來替換。
  • 普通函數是將程序執行轉移到被調用函數所存放的內存地址,當函數執行完后,返回到執行此函數前的地方。轉移操作需要保護現場,被調函數執行完后,再恢復現場,該過程需要較大的資源開銷。

宏定義(define)和內聯函數(inline)的區別

  1. 內聯函數是在編譯時展開,而宏在編譯預處理時展開;在編譯的時候,內聯函數直接被嵌入到目標代碼中去,而宏只是一個簡單的文本替換。
  2. 內聯函數是真正的函數,和普通函數調用的方法一樣,在調用點處直接展開,避免了函數的參數壓棧操作,減少了調用的開銷。而宏定義編寫較為復雜,常需要增加一些括號來避免歧義。
  3. 宏定義只進行文本替換,不會對參數的類型、語句能否正常編譯等進行檢查。而內聯函數是真正的函數,會對參數的類型、函數體內的語句編寫是否正確等進行檢查。
#include <iostream>#define MAX(a, b) ((a) > (b) ? (a) : (b))using namespace std;inline int fun_max(int a, int b)
{return a > b ? a : b;
}int main()
{int var = 1;cout << MAX(var, 5) << endl;     cout << fun_max(var, 0) << endl; return 0;
}
/*
程序運行結果:
5
1*/

new/delete和malloc/free

new的作用

new 是 C++ 中的關鍵字,用來動態分配內存空間,實現方式如下:

int *p = new int[5]; 

new和malloc分別如何判斷是否申請到內存

  • malloc :成功申請到內存,返回指向該內存的指針;分配失敗,返回 NULL 指針。
  • new :內存分配成功,返回該對象類型的指針;分配失敗,拋出 bac_alloc 異常。

delete 實現原理?delete 和 delete[] 的區別?

delete 的實現原理

  • 首先執行該對象所屬類的析構函數;
  • 進而通過調用 operator delete 的標準庫函數來釋放所占的內存空間。

delete 和 delete [] 的區別

  • delete 用來釋放單個對象所占的空間,只會調用一次析構函數;
  • delete [] 用來釋放數組空間,會對數組中的每個成員都調用一次析構函數。

new和malloc的區別

在使用的時候 newdelete 搭配使用,mallocfree 搭配使用。

  • mallocfree 是庫函數,而 newdelete 是關鍵字。
  • new 申請空間時,無需指定分配空間的大小,編譯器會根據類型自行計算;malloc 在申請空間時,需要確定所申請空間的大小。
  • new 申請空間時,返回的類型是對象的指針類型,無需強制類型轉換,是類型安全的操作符;malloc 申請空間時,返回的是 void* 類型,需要進行強制類型的轉換,轉換為對象類型的指針。
  • new 分配失敗時,會拋出 bad_alloc 異常,malloc 分配失敗時返回空指針。
  • 對于自定義的類型,new 首先調用 operator new() 函數申請空間(底層通過 malloc 實現),然后調用構造函數進行初始化,最后返回自定義類型的指針;delete 首先調用析構函數,然后調用 operator delete() 釋放空間(底層通過 free 實現)。mallocfree 無法進行自定義類型的對象的構造和析構。
  • new 操作符從自由存儲區上為對象動態分配內存,而 malloc 函數從堆上動態分配內存。(自由存儲區不等于堆)

(下表來自:C/C++——C++中new與malloc的10點區別)

特征new/deletemalloc/free
分配內存的位置自由存儲區
內存分配失敗返回值完整類型指針void*
內存分配失敗返回值默認拋出異常返回NULL
分配內存的大小由編譯器根據類型計算得出必須顯式指定字節數
處理數組有處理數組的new版本new[]需要用戶計算數組的大小后進行內存分配
已分配內存的擴充無法直觀地處理使用realloc簡單完成
是否相互調用可以,看具體的operator new/delete實現不可調用new
分配內存時內存不足客戶能夠指定處理函數或重新制定分配器無法通過用戶代碼進行處理
函數重載允許不允許
構造函數與析構函數調用不調用
  • malloc給你的就好像一塊原始的土地,你要種什么需要自己在土地上來播種
  • 而new幫你劃好了田地的分塊(數組),幫你播了種(構造函數),還提供其他的設施給你使用:

malloc 的原理?malloc 的底層實現?

malloc 的原理:

  • 當開辟的空間小于 128K 時,調用 brk() 函數,通過移動 _enddata 來實現;
  • 當開辟空間大于 128K 時,調用 mmap() 函數,通過在虛擬地址空間中開辟一塊內存空間來實現。

malloc 的底層實現

  • brk() 函數實現原理:向高地址的方向移動指向數據段的高地址的指針 _enddata
  • mmap 內存映射原理:
    1. 進程啟動映射過程,并在虛擬地址空間中為映射創建虛擬映射區域;
    2. 調用內核空間的系統調用函數 mmap(),實現文件物理地址和進程虛擬地址的一一映射關系;
    3. 進程發起對這片映射空間的訪問,引發缺頁異常,實現文件內容到物理內存(主存)的拷貝。

class、struct、union

C 和 C++ struct 的區別?

  • 在 C 語言中 struct 是用戶自定義數據類型;在 C++ 中 struct 是抽象數據類型,支持成員函數的定義。
  • C 語言中 struct 沒有訪問權限的設置,是一些變量的集合體,不能定義成員函數;C++ 中 struct 可以和類一樣,有訪問權限,并可以定義成員函數。
  • C 語言中 struct 定義的自定義數據類型,在定義該類型的變量時,需要加上 struct 關鍵字,例如:struct A var;,定義 A 類型的變量;而 C++ 中,不用加該關鍵字,例如:A var;

為什么有了 class 還保留 struct?

C++ 是在 C 語言的基礎上發展起來的,為了與 C 語言兼容,C++ 中保留了 struct

struct 和 union 的區別

說明:union 是聯合體,struct 是結構體。

區別:

  • 聯合體和結構體都是由若干個數據類型不同的數據成員組成。使用時,聯合體只有一個有效的成員;而結構體所有的成員都有效。
  • 對聯合體的不同成員賦值,將會對覆蓋其他成員的值,而對于結構體的對不同成員賦值時,相互不影響。
  • 聯合體的大小為其內部所有變量的最大值,按照最大類型的倍數進行分配大小;結構體分配內存的大小遵循內存對齊原則。
#include <iostream>
using namespace std;typedef union
{char c[10];char cc1; // char 1 字節,按該類型的倍數分配大小
} u11;typedef union
{char c[10];int i; // int 4 字節,按該類型的倍數分配大小
} u22;typedef union
{char c[10];double d; // double 8 字節,按該類型的倍數分配大小
} u33;typedef struct s1
{char c;   // 1 字節double d; // 1(char)+ 7(內存對齊)+ 8(double)= 16 字節
} s11;typedef struct s2
{char c;   // 1 字節char cc;  // 1(char)+ 1(char)= 2 字節double d; // 2 + 6(內存對齊)+ 8(double)= 16 字節
} s22;typedef struct s3
{char c;   // 1 字節double d; // 1(char)+ 7(內存對齊)+ 8(double)= 16 字節char cc;  // 16 + 1(char)+ 7(內存對齊)= 24 字節
} s33;int main()
{cout << sizeof(u11) << endl; // 10cout << sizeof(u22) << endl; // 12cout << sizeof(u33) << endl; // 16cout << sizeof(s11) << endl; // 16cout << sizeof(s22) << endl; // 16cout << sizeof(s33) << endl; // 24cout << sizeof(int) << endl;    // 4cout << sizeof(double) << endl; // 8return 0;
}

class 和 struct 的異同

  • struct 和 class 都可以自定義數據類型,也支持繼承操作。
  • struct 中默認的訪問級別是 public,默認的繼承級別也是 public;class 中默認的訪問級別是 private,默認的繼承級別也是 private。
  • 當 class 繼承 struct 或者 struct 繼承 class 時,默認的繼承級別取決于 class 或 struct 本身, class(private 繼承),struct(public 繼承),即取決于派生類的默認繼承級別。
  • class 可以用于定義模板參數,struct 不能用于定義模板參數。
struct A{}class B : A{}; // private 繼承 
struct C : B{}// public 繼承

volatile

valatile的作用?是否具有原子性?

  • volatile 的作用:當對象的值可能在程序的控制或檢測之外被改變時,應該將該對象聲明為 volatile,告知編譯器不應對這樣的對象進行優化。

  • volatile 不具有原子性。

  • volatile 對編譯器的影響:使用該關鍵字后,編譯器不會對相應的對象進行優化,即不會將變量從內存緩存到寄存器中,防止多個線程有可能使用內存中的變量,有可能使用寄存器中的變量,從而導致程序錯誤。

什么情況下一定要用 volatile, 能否和 const 一起使用?

使用 volatile 關鍵字的場景:

  • 當多個線程都會用到某一變量,并且該變量的值有可能發生改變時,需要用 volatile 關鍵字對該變量進行修飾;
  • 中斷服務程序中訪問的變量或并行設備的硬件寄存器的變量,最好用 volatile 關鍵字修飾。

volatile 關鍵字和 const 關鍵字可以同時使用,某種類型可以既是 volatile 又是 const ,同時具有二者的屬性。

extern、sizeof、memmove、strcpy、auto雜問

extern C 的作用?

當 C++ 程序 需要調用 C 語言編寫的函數,C++ 使用鏈接指示,即 extern "C" 指出任意非 C++ 函數所用的語言。

舉例:

// 可能出現在 C++ 頭文件<cstring>中的鏈接指示
extern "C"{int strcmp(const char*, const char*);
}

sizeof(1==1) 在 C 和 C++ 中分別是什么結果?

C 語言代碼:

#include<stdio.h>void main(){printf("%d\n", sizeof(1==1));
}/*
運行結果:
4
*/

C++ 代碼:

#include <iostream>
using namespace std;int main() {cout << sizeof(1==1) << endl;return 0;
}/*
1
*/

C語言:

sizeof(1 == 1) === sizeof(1)按照整數處理,所以是4字節,這里也有可能是8字節(看操作系統)

C++:

因為有bool 類型,sizeof(1 == 1) == sizeof(true) 按照bool類型處理,所以是1個字節

memmove與memcpy

詳見:memmove 和 memcpy的區別以及處理內存重疊問題

strcpy 函數有什么缺陷?

strcpy 函數的缺陷:strcpy 函數不檢查目的緩沖區的大小邊界,而是將源字符串逐一的全部賦值給目的字符串地址起始的一塊連續的內存空間,同時加上字符串終止符,會導致其他變量被覆蓋。

#include <iostream>
#include <cstring>
using namespace std;int main()
{int var = 0x11112222;char arr[10];cout << "Address : var " << &var << endl;cout << "Address : arr " << &arr << endl;strcpy(arr, "hello world!");cout << "var:" << hex << var << endl; // 將變量 var 以 16 進制輸出cout << "arr:" << arr << endl;return 0;
}/*
Address : var 0x23fe4c
Address : arr 0x23fe42
var:11002164
arr:hello world!
*/

說明:從上述代碼中可以看出,變量 var 的后六位被字符串 "hello world!""d!\0" 這三個字符改變,這三個字符對應的 ascii 碼的十六進制為:\0(0x00),!(0x21),d(0x64)。
原因:變量 arr 只分配的 10 個內存空間,通過上述程序中的地址可以看出 arrvar 在內存中是連續存放的,但是在調用 strcpy 函數進行拷貝時,源字符串 "hello world!" 所占的內存空間為 13,因此在拷貝的過程中會占用 var 的內存空間,導致 var 的后六位被覆蓋。

在這里插入圖片描述

auto 類型推導的原理

auto 類型推導的原理:

編譯器根據初始值來推算變量的類型,要求用 auto 定義變量時必須有初始值。編譯器推斷出來的 auto 類型有時和初始值類型并不完全一樣,編譯器會適當改變結果類型使其更符合初始化規則。

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

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

相關文章

memcpy和memmove的區別以及內存重疊問題

memcpy和memmove的區別以及內存重疊問題 轉自&#xff1a;https://www.codecomeon.com/posts/89/ 區別 memcpy() 和 memmove() 都是C語言中的庫函數&#xff0c;在頭文件 string.h 中&#xff0c;作用是拷貝一定長度的內存的內容&#xff0c;原型分別如下&#xff1a; void…

從頭搭建一個深度學習框架

從頭搭建一個深度學習框架 轉自&#xff1a;Build a Deep Learning Framework From Scratch 代碼&#xff1a;https://github.com/borgwang/tinynn 當前深度學習框架越來越成熟&#xff0c;對于使用者而言封裝程度越來越高&#xff0c;好處就是現在可以非常快速地將這些框架作為…

關于python import的sys.path路徑問題

關于python import的sys.path路徑問題 sys.path 先說一下 sys.path 這個變量&#xff0c;該變量需要導入 sys 官方庫方可使用&#xff0c;它是一個列表&#xff0c;是當前 python 文件 import 庫時會逐個搜索列表中的路徑。 初始化 sys.path 從這些位置初始化&#xff1a; …

python pdb調試基本命令整理

python pdb調試基本命令整理 使用簡介 啟動調試 侵入式 在 py 文件內部設置&#xff1a; import pdb; pdb.set_trace()程序會在運行到這一行時停下來&#xff0c;進入 pdb 交互。 非侵入式 在運行 py 腳本時&#xff1a; python -m pdb main.py程序會在一啟動時就進入 pdb 交…

Docker概念理解

Docker概念理解 本文非Docker命令大全&#xff0c;而是對Docker的概念、原理等作說明&#xff0c;適合有一定實操經驗后來加深理解。 轉自&#xff1a;docker從入門到實踐 Docker簡介 本章將帶領你進入 Docker 的世界。 什么是 Docker&#xff1f; 用它會帶來什么樣的好處&a…

Dockerfile詳解

Dockerfile詳解 轉自&#xff1a;https://yeasy.gitbook.io/docker_practice/ 使用Dockerfile定制鏡像 從剛才的 docker commit 的學習中&#xff0c;我們可以了解到&#xff0c;鏡像的定制實際上就是定制每一層所添加的配置、文件。如果我們可以把每一層修改、安裝、構建、操…

Dockerfile最佳實踐

Dockerfile最佳實踐 本文是原作者對 Docker 官方文檔中 Best practices for writing Dockerfiles 的理解與翻譯。 轉自&#xff1a;附錄四&#xff1a;Dockerfile 最佳實踐 一般性指南和建議 容器應該是短暫的 通過 Dockerfile 構建的鏡像所啟動的容器應該盡可能短暫&#xf…

Linux內存背后的那些神秘往事

Linux內存背后的那些神秘往事 作者&#xff1a;大白斯基&#xff08;公眾號&#xff1a;后端研究所&#xff09; 轉自&#xff1a;https://mp.weixin.qq.com/s/l_YdpyHht5Ayvrc7LFZNIA 前言 大家好&#xff0c;我的朋友們&#xff01; CPU、IO、磁盤、內存可以說是影響計算機…

mmdeploy快速上手

mmdeploy快速上手 若要將使用 openmmlab 的框架&#xff08;如mmdet、mmcls&#xff09;等訓練的模型進行快速部署&#xff0c;同樣來自 openmmlab 的 mmdeploy 無疑是最合適的選擇&#xff0c;本文將簡單地完成一個 Faster RCNN 模型的部署。 配置 本文基于如下軟硬件配置&…

精簡CUDA教程——CUDA Driver API

精簡CUDA教程——CUDA Driver API tensorRT從零起步邁向高性能工業級部署&#xff08;就業導向&#xff09; 課程筆記&#xff0c;講師講的不錯&#xff0c;可以去看原視頻支持下。 Driver API概述 CUDA 的多級 API CUDA 的 API 有多級&#xff08;下圖&#xff09;&#xff…

CUDA編程入門極簡教程

CUDA編程入門極簡教程 轉自&#xff1a;CUDA編程入門極簡教程 作者&#xff1a;小小將 前言 2006年&#xff0c;NVIDIA公司發布了CUDA&#xff0c;CUDA是建立在NVIDIA的CPUs上的一個通用并行計算平臺和編程模型&#xff0c;基于CUDA編程可以利用GPUs的并行計算引擎來更加高效地…

精簡CUDA教程——CUDA Runtime API

精簡CUDA教程——CUDA Runtime API tensorRT從零起步邁向高性能工業級部署&#xff08;就業導向&#xff09; 課程筆記&#xff0c;講師講的不錯&#xff0c;可以去看原視頻支持下。 Runtime API 概述 環境 圖中可以看到&#xff0c;Runtime API 是基于 Driver API 之上開發的…

Python并發——concurrent.futures梳理

Python并發——concurrent.futures梳理 參考官方文檔&#xff1a; concurrent.futures — 啟動并行任務 Executor對象 class concurrent.funtures.Executor該抽象類是 ThreadPoolExecutor 和 ProcessPoolExecutor 的父類&#xff0c;提供異步執行調用方法。要通過它的子類調用…

TensorRT ONNX 基礎

TensorRT ONNX 基礎 tensorRT從零起步邁向高性能工業級部署&#xff08;就業導向&#xff09; 課程筆記&#xff0c;講師講的不錯&#xff0c;可以去看原視頻支持下。 概述 TensorRT 的核心在于對模型算子的優化&#xff08;合并算子、利用當前 GPU 特性選擇特定的核函數等多種…

回文子串、回文子序列相關題目

回文子串、回文子序列相關題目 回文子串是要連續的&#xff0c;回文子序列可不是連續的。 516. 最長回文子序列 dp數組含義&#xff1a;dp[i][j]dp[i][j]dp[i][j] 表示子序列 s[i,j]s[i,j]s[i,j] 中的最長回文子序列的長度。 dp數組初始化&#xff1a;子序列長度為 1 時&am…

mmdetection tools工具梳理

mmdetection tools工具梳理 mmdetection 是一個非常好用的開源目標檢測框架&#xff0c;我們可以用它方便地訓練自己的目標檢測模型&#xff0c;mmdetection 項目倉庫提供許多實用的工具來實現幫助我們進行各種測試。本篇將梳理以下 mmdetection 項目倉庫 tools 目錄下的各種實…

TensorRT ONNX 基礎(續)

TensorRT ONNX 基礎&#xff08;續&#xff09; PyTorch正確導出ONNX 幾條推薦的原則&#xff0c;可以減少潛在的錯誤&#xff1a; 對于任何使用到 shape、size 返回值的參數時&#xff0c;例如 tensor.view(tensor.size(0), -1) 這類操作&#xff0c;避免直接使用 tensor.s…

frp實現內網穿透極簡教程

frp實現內網穿透極簡教程 本文是內網穿透極簡教程&#xff0c;為求簡潔&#xff0c;我們不介紹為什么內網穿透也不介紹其原理&#xff0c;這里假設各位讀者都已經明確的知道自己的目的&#xff0c;本文僅介紹如何安裝配置 frp 實現內網穿透。 簡單來說&#xff0c;內網穿透就…

圖像預處理之warpaffine與雙線性插值及其高性能實現

圖像預處理之warpaffine與雙線性插值及其高性能實現 視頻講解&#xff1a;https://www.bilibili.com/video/BV1ZU4y1A7EG 代碼Repo&#xff1a;https://github.com/shouxieai/tensorRT_Pro 本文為視頻講解的個人筆記。 warpaffine矩陣變換 對于坐標點的變換&#xff0c;我們通…

LeetCode-10 正則表達式匹配

LeetCode-10 正則表達式匹配 動態規劃 10. 正則表達式匹配 dp數組含義&#xff1a;dp[i][j]dp[i][j]dp[i][j] 表示 s[0:i?1]s[0:i-1]s[0:i?1] 能否被 p[0:j?1]p[0:j-1]p[0:j?1] 成功匹配。 狀態轉移方程 &#xff1a; 如果 s[i?1]p[j?1]s[i-1]p[j-1]s[i?1]p[j?1] …