當前位置:首頁 > 公眾號精選 > C語言與CPP編程
[導讀]文章是由我筆試面試騰訊筆記整理而來,主要是針對面試的C++后臺開發(fā)崗位,涵蓋了大部分C++后臺開發(fā)相關可能會考察和被問到的技術點。自認為這篇筆記是比較全面的總結,不管你是已經(jīng)工作準備參加社招,還是在校學生準備參加校招,筆記都可以作為技術面試準備階段參考查閱,查缺補漏。

文章是由我筆試面試騰訊筆記整理而來,主要是針對面試的C++后臺開發(fā)崗位,涵蓋了大部分C++后臺開發(fā)相關可能會考察和被問到的技術點。 

自認為這篇筆記是比較全面的總結,不管你是已經(jīng)工作準備參加社招,還是在校學生準備參加校招,筆記都可以作為技術面試準備階段參考查閱,查缺補漏。

筆記是基礎C++知識點總結,沒有過多的闡述后臺開發(fā)的系統(tǒng)架構和分布式后臺服務設計相關,還有c++11新特性,這些筆試面試也會被問到但不在這篇討論范圍,可以關注我后面有時間再補上。

閱讀提示

文章約12839字,閱讀時長預計33分鐘。建議關注收藏方便回頭查閱。


gdb調(diào)試命令

step和next的區(qū)別?

當前l(fā)ine有函數(shù)調(diào)用的時候,next會直接執(zhí)行到下一句 ,step會進入函數(shù).

查看內(nèi)存

(gdb)p &a //打印變量地址

(gdb)x 0xbffff543 //查看內(nèi)存單元內(nèi)變量

0xbffff543: 0x12345678

(gdb) x /4xb 0xbffff543 //單字節(jié)查看4個內(nèi)存單元變量的值

0xbffff543: 0x78 0x56 0x34 0x12

多線程調(diào)試

(gdb) info threads:查看GDB當前調(diào)試的程序的各個線程的相關信息

(gdb) thread threadno:切換當前線程到由threadno指定的線程

break filename:linenum thread all ? 在所有線程相應行設置斷點,注意如果主線程不會執(zhí)行到該行,并且啟動all-stop模式,主線程執(zhí)行n或s會切換過去

set scheduler-locking off|on\step ? ?默認off,執(zhí)行s或c其它線程也同步執(zhí)行。on,只有當前線程執(zhí)行。step,只有當前線程執(zhí)行

show scheduler-locking ? ? ? ? ?顯示當前模式

thread apply all command ? ? ? ?每個線程執(zhí)行同意命令,如bt?;蛘遲hread apply 1 3 bt,即線程1,3執(zhí)行bt。

查看調(diào)用堆棧

(gdb)bt

(gdb)f 1 幀簡略信息

(gdb)info f 1 幀詳細信息

斷點

b test.cpp:11

b test.cpp:main

gdb attach 調(diào)試方法:

gdb->file xxxx->attach pid->這時候進程是停止的->c 繼續(xù)運行

帶參數(shù)調(diào)試

輸入?yún)?shù)命令set args 后面加上程序所要用的參數(shù),注意,不再帶有程序名,直接加參數(shù),如:

(gdb)set args -l a -C abc

list命令

list linenum  顯示程序第linenum行的周圍的程序

list function  顯示程序名為function的函數(shù)的源程序


static關鍵字的作用


軟硬鏈接

ln -s 源文件 目標文件, ln -s / /home/good/linkname鏈接根目錄/到/home/good/linkname

1、軟鏈接就是:“l(fā)n –s 源文件 目標文件”,只會在選定的位置上生成一個文件的鏡像,不會占用磁盤空間,類似于windows的快捷方式。

2、硬鏈接ln源文件目標文件,沒有參數(shù)-s, 會在選定的位置上生成一個和源文件大小相同的文件,無論是軟鏈接還是硬鏈接,文件都保持同步變化。


函數(shù)指針

函數(shù)指針 int (*func)(int, int)

函數(shù)指針數(shù)組 int (*funcArry[10])(int, int)

const int* p; 指向const int的指針

int const* p; 同上

int* const p; const指針

設計模式

單例模式

觀察者模式(也叫發(fā)布訂閱模式)

工廠模式 三種:簡單工廠模式、工廠方法模式、抽象工廠模式

為什么要用工廠模式?

原因就是對上層的使用者隔離對象創(chuàng)建的過程;或者是對象創(chuàng)建的過程復雜,使用者不容易掌握;或者是對象創(chuàng)建要滿足某種條件,這些條件是業(yè)務的需求也好,是系統(tǒng)約束也好,沒有必要讓上層使用者掌握,增加別人開發(fā)的難度。所以,到這時我們應該清楚了,無論是工廠模式,還是上面的戰(zhàn)友說的開閉原則,都是為了隔離一些復雜的過程,使得這些復雜的過程不向外暴露,如果暴露了這些過程,會對使用者增加麻煩,這也就是所謂的團隊合作。

數(shù)據(jù)結構

各種排序算法

堆排序

關鍵:1.初始建堆從最后一個非葉節(jié)點開始調(diào)整 2.篩選從頂點開始往下調(diào)整

通俗易懂的快排

二叉樹定理

度為2節(jié)點數(shù) = 葉子節(jié)點數(shù) - 1

證明:樹枝數(shù)=節(jié)點數(shù)-1, n00 +n11 +n2*2 = n0+n1+n2-1 (n0代表度為0的節(jié)點數(shù),以此類推)


互斥鎖

pthread_mutex_t m_mutex; pthread_mutex_init(&m_mutex, NULL)等效于pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER pthread_mutex_lock(&m_mutex); pthread_mutex_unlock(&m_mutex) pthread_mutex_destroy(&m_mutex) int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); bool g_flag = false; void* t1(void* arg) {  cout << "create t1 thread success" << endl;  pthread_mutex_lock(&m_mutex);  g_flag = true;  pthread_mutex_unlock(&m_mutex); } void* t2(void* arg) {  cout << "create t2 thread success" << endl;  pthread_mutex_lock(&m_mutex);  g_flag = false;  pthread_mutex_unlock(&m_mutex); } int main(int argc, char* argv[]) {  pthread_t tid1, tid2;  pthread_create(&tid1, NULL, t1, NULL);  sleep(2);  pthread_create(&tid2, NULL, t2, NULL);  pthread_join(tid1, NULL);  pthread_join(tid2, NULL); }


大小端轉(zhuǎn)換

#define BigLittleSwap32(A) ((((uint32)(A) & 0xff000000) >> 24) | \  (((uint32)(A) & 0x00ff0000) >> 8) | \  (((uint32)(A) & 0x0000ff00) << 8) | \  (((uint32)(A) & 0x000000ff) << 24))


io多路復用

為什么 IO 多路復用要搭配非阻塞IO

設置非阻塞 io fcntl(sockfd, F_SETFL, O_NONBLOCK);

select

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); void FD_CLR(int fd, fd_set *set); int FD_ISSET(int fd, fd_set *set); void FD_SET(int fd, fd_set *set); void FD_ZERO(fd_set *set); fd_set rdfds; struct timeval tv; int ret; FD_ZERO(&rdfds); FD_SET(socket, &rdfds); tv.tv_sec = 1; tv.tv_uses = 500; ret = select (socket + 1, %rdfds, NULL, NULL, &tv); if(ret < 0) perror (“select”); else if (ret = = 0) printf(“time out”); else {  printf(“ret = %d/n”,ret);  if(FD_ISSET(socket, &rdfds)){   /* 讀取socket句柄里的數(shù)據(jù) */ }注意select函數(shù)的第一個參數(shù),是所有加入集合的句柄值的最大那個那個值還要加1.比如我們創(chuàng)建了3個句柄;


poll實現(xiàn)

poll的實現(xiàn)和select非常相似,只是描述fd集合的方式不同,poll使用pollfd結構而不是select的fd_set結構,其他的都差不多,管理多個描述符也是進行輪詢,根據(jù)描述符的狀態(tài)進行處理,但是poll沒有最大文件描述符數(shù)量的限制。poll和select同樣存在一個缺點就是,包含大量文件描述符的數(shù)組被整體復制于用戶態(tài)和內(nèi)核的地址空間之間,而不論這些文件描述符是否就緒,它的開銷隨著文件描述符數(shù)量的增加而線性增大。

epoll原理

https://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html

#include  int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

epoll對文件描述符的操作有兩種模式:LT(level trigger)和ET(edge trigger)。LT模式是默認模式,LT模式與ET模式的區(qū)別如下:

LT模式:當epoll_wait檢測到描述符事件發(fā)生并將此事件通知應用程序,應用程序可以不立即處理該事件。下次調(diào)用epoll_wait時,會再次響應應用程序并通知此事件。

ET模式:當epoll_wait檢測到描述符事件發(fā)生并將此事件通知應用程序,應用程序必須立即處理該事件。如果不處理,下次調(diào)用epoll_wait時,不會再次響應應用程序并通知此事件。

ET模式在很大程度上減少了epoll事件被重復觸發(fā)的次數(shù),因此效率要比LT模式高。epoll工作在ET模式的時候,

必須使用非阻塞套接口,以避免由于一個文件句柄的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。

Epoll ET模型下,為什么每次EPOLLIN事件都會帶一次EPOLLOUT事件:https://bbs.csdn.net/topics/390630226

udp套接字

#include  ssize_t sendto(int sockfd, void *buff, size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *addr, socklen_t *addrlen);


網(wǎng)絡套接字

udp原理與套接字

udp服務端:

sockListener=socket(AF_INET,SOCK_DGRAM,0) bind(sockListener,(struct sockaddr*)&addrListener,sizeof(addrListener)) nMsgLen=recvfrom(sockListener,szBuf,1024,0,(struct sockaddr*)&addrClient,&addrLen) 

udp客戶端

sockClient=socket(AF_INET,SOCK_DGRAM,0); bind(sockClient,(struct sockaddr*)&addrLocal,sizeof(addrLocal)) FD_ZERO(&setHold); FD_SET(STDIN_FILENO,&setHold); FD_SET(sockClient,&setHold); cout<<"you can type in sentences any time"<<endl; while(true) {  setTest=setHold;  nReady=select(sockClient+1,&setTest,NULL,NULL,NULL);  if(FD_ISSET(0,&setTest))  {  nMsgLen=read(0,szMsg,1024);  write(sockClient,szMsg,nMsgLen);  }  if(FD_ISSET(sockClient,&setTest))  {  nMsgLen=read(sockClient,szRecv,1024);  szRecv[nMsgLen]='\0';  cout<<"read:"<<szRecv<<endl;  } } 

UDP中使用 connect 函數(shù)成為已連接的套接字

已連接 UDP 套接字 相對于 未連接 UDP 套接字 會有以下的變化:

  1. 不能給輸出操作指定目的 IP 地址和端口號(因為調(diào)用 connect 函數(shù)時已經(jīng)指定),即不能使用 sendto 函數(shù),而是使用 write 或 send 函數(shù)。寫到已連接 UDP 套接字上的內(nèi)容都會自動發(fā)送到由 connect 指定的協(xié)議地址;

  2. 不必使用 recvfrom 函數(shù)以獲悉數(shù)據(jù)報的發(fā)送者,而改用 read、recv 或 recvmsg 函數(shù)。在一個已連接 UDP 套接字上,由內(nèi)核為輸入操作返回的數(shù)據(jù)報只有那些來自 connect 函數(shù)所指定的協(xié)議地址的數(shù)據(jù)報。目的地為這個已連接 UDP 套接字的本地協(xié)議地址,發(fā)源地不是該套接字早先 connect 到的協(xié)議地址的數(shù)據(jù)報,不會投遞到該套接字。即只有發(fā)源地的協(xié)議地址與 connect 所指定的地址相匹配才可以把數(shù)據(jù)報傳輸?shù)皆撎捉幼帧_@樣已連接 UDP 套接字只能與一個對端交換數(shù)據(jù)報;

  3. 由已連接 UDP 套接字引發(fā)的異步錯誤會返回給它們所在的進程,而未連接 UDP 套接字不會接收任何異步錯誤;

tcp套接字

服務端:

listenfd = socket(AF_INET , SOCK_STREAM , 0) bind(listenfd , (struct sockaddr*)&servaddr , sizeof(servaddr)) listen(listenfd , LISTENQ) connfd = accept(listenfd , (struct sockaddr *)&cliaddr , &clilen)) n = read(connfd , buff , MAX_LINE) write(connfd , buff , n)

客戶端:

sockfd = socket(AF_INET , SOCK_STREAM , 0) connect(sockfd , (struct sockaddr *)&servaddr , sizeof(servaddr)) write(sockfd , sendline , strlen(sendline))

IP分片與重組

參考1

參考2

MTU是1500是指的以太網(wǎng)的MTU,可以用 netstat -i 命令查看這個值。如果IP層有數(shù)據(jù)包要傳,而且數(shù)據(jù)包的長度超過了MTU,

那么IP層就要對數(shù)據(jù)包進行分片(fragmentation)操作,使每一片的長度都小于或等于MTU。

我們假設要傳輸一個UDP數(shù)據(jù)包,以太網(wǎng)的MTU為1500字節(jié),一般IP首部為20字節(jié),UDP首部為8字節(jié),數(shù)據(jù)的凈荷(payload)

部分預留是1500-20-8=1472字節(jié)。如果數(shù)據(jù)部分大于1472字節(jié),就會出現(xiàn)分片現(xiàn)象,

偏移量的單位為8Byte

以ID標示是不是同一個分片,以偏移量標示在報文里的位置,每個不完整的ID報文有一個等待計時器,到時丟棄IP層不保證能夠送達,

如果丟了上層自己處理參考rfc 791

IP報文長度單位口訣

4字節(jié)單位- 首部長度單位 1字節(jié)單位-總長度單位 ?8字節(jié)單位-片偏移單位

STL容器

vector與list

1.vector數(shù)據(jù)結構

vector和數(shù)組類似,擁有一段連續(xù)的內(nèi)存空間,并且起始地址不變。

因此能高效的進行隨機存取,時間復雜度為o(1);

但因為內(nèi)存空間是連續(xù)的,所以在進行插入和刪除操作時,會造成內(nèi)存塊的拷貝,時間復雜度為o(n)。

另外,當數(shù)組中內(nèi)存空間不夠時,會重新申請一塊內(nèi)存空間并進行內(nèi)存拷貝。

2.list數(shù)據(jù)結構

list是由雙向鏈表實現(xiàn)的,因此內(nèi)存空間是不連續(xù)的。

只能通過指針訪問數(shù)據(jù),所以list的隨機存取非常沒有效率,時間復雜度為o(n);

但由于鏈表的特點,能高效地進行插入和刪除。


Vector動態(tài)內(nèi)存分配

這個問題其實很簡單,在調(diào)用push_back時,若當前容量已經(jīng)不能夠放入心得元素(capacity=size),那么vector會重新申請一塊內(nèi)存,把之前的內(nèi)存里的元素拷貝到新的內(nèi)存當中,然后把push_back的元素拷貝到新的內(nèi)存中,最后要析構原有的vector并釋放原有的內(nèi)存。所以說這個過程的效率是極低的,為了避免頻繁的分配內(nèi)存,C++每次申請內(nèi)存都會成倍的增長,例如之前是4,那么重新申請后就是8,以此類推。當然不一定是成倍增長,比如在我的編譯器環(huán)境下實測是0.5倍增長,之前是4,重新申請后就是6

TinySTL


預處理指令

#pragma once 防止頭文件重復引用

一字節(jié)對齊

#pragma pack(push, 1)

#pragma pack(pop)

class面向?qū)ο?/span>

類繼承

class LayerManager : public ILayerManager{};

為什么析構函數(shù)要是虛函數(shù)?

基類指針可以指向派生類的對象(多態(tài)性),如果刪除該指針delete []p;就會調(diào)用該指針指向的派生類析構函數(shù),而派生類的析構函數(shù)又自動調(diào)用基類的析構函數(shù),這樣整個派生類的對象完全被釋放。如果析構函數(shù)不被聲明成虛函數(shù),則編譯器實施靜態(tài)綁定,在刪除基類指針時,只會調(diào)用基類的析構函數(shù)而不調(diào)用派生類析構函數(shù),這樣就會造成派生類對象析構不完全。所以,將析構函數(shù)聲明為虛函數(shù)是十分必要的。


覆蓋虛函數(shù)機制

在某些情況下,希望覆蓋虛函數(shù)機制并強制函數(shù)調(diào)用使用虛函數(shù)的特定版

本,這里可以使用作用域操作符:

Item_base *baseP = &derived; // calls version from the base class regardless of the dynamic type of baseP double d = baseP->Item_base::net_price(42);

這段代碼強制將 net_price 調(diào)用確定為 Item_base 中定義的版本,該調(diào)用

將在編譯時確定。只有成員函數(shù)中的代碼才應該使用作用域操作符覆蓋虛函數(shù)機制。

為什么會希望覆蓋虛函數(shù)機制?最常見的理由是為了派生類虛函數(shù)調(diào)用基類中的版本。在這種情況下,基類版本可以完成繼承層次中所有類型的公共任務,而每個派生類型只添加自己的特殊工作。

例如,可以定義一個具有虛操作的 Camera 類層次。Camera 類中的 display函數(shù)可以顯示所有的公共信息,派生類(如 PerspectiveCamera)可能既需要顯示公共信息又需要顯示自己的獨特信息??梢燥@式調(diào)用 Camera 版本以顯示公共信息,而不是在 PerspectiveCamera 的 display 實現(xiàn)中復制 Camera 的操作。

在這種情況下,已經(jīng)確切知道調(diào)用哪個實例,因此,不需要通過虛函數(shù)機制。派生類虛函數(shù)調(diào)用基類版本時,必須顯式使用作用域操作符。如果派生類函數(shù)忽略了這樣做,則函數(shù)調(diào)用會在運行時確定并且將是一個自身調(diào)用,從而導致無窮遞歸。

名字沖突與繼承

雖然可以直接訪問基類成員,就像它是派生類成員一樣,但是成員保留了它的基類成員資格。一般我們并不關心是哪個實際類包含成員,通常只在基類和派生類共享同一名字時才需要注意。

與基類成員同名的派生類成員將屏蔽對基類成員的直接訪問。

struct Base {  Base(): mem(0) { }  protected:  int mem; }; struct Derived : Base  {  Derived(int i): mem(i) { } // initializes Derived::mem  int get_mem() { return mem; } // returns Derived::mem  protected:  int mem; // hides mem in the base }; get_mem 中對 mem 的引用被確定為使用 Derived 中的名字。如果編寫如下代碼: Derived d(42); cout << d.get_mem() << endl; // prints 42

則輸出將是 42。

使用作用域操作符訪問被屏蔽成員

可以使用作用域操作符訪問被屏蔽的基類成員:

struct Derived : Base  {  int get_base_mem() { return Base::mem; } };

作用域操作符指示編譯器在 Base 中查找 mem。

設計派生類時,只要可能,最好避免與基類數(shù)據(jù)成員的名字相同


類成員函數(shù)的重載、覆蓋和隱藏區(qū)別?

a.成員函數(shù)被重載的特征:

(1)相同的范圍(在同一個類中);

(2)函數(shù)名字相同;

(3)參數(shù)不同;

(4)virtual 關鍵字可有可無。

b.覆蓋是指派生類函數(shù)覆蓋基類函數(shù),特征是:

(1)不同的范圍(分別位于派生類與基類);

(2)函數(shù)名字相同;

(3)參數(shù)相同;

(4)基類函數(shù)必須有virtual 關鍵字。

c.“隱藏”是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù),規(guī)則如下:

(1)如果派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)不同。此時,不論有無virtual關鍵字,基類的函數(shù)將被隱藏(注意別與重載混淆,僅同名就可以)。

(2)如果派生類的函數(shù)與基類的函數(shù)同名,并且參數(shù)也相同,但是基類函數(shù)沒有virtual 關鍵字。此時,基類的函數(shù)被隱藏(注意別與覆蓋混淆)

純虛函數(shù)

class Disc_item : public Item_base  {  public:  double net_price(std::size_t) const = 0; };

含有(或繼承)一個或多個純虛函數(shù)的類是抽象基類。除了作

為抽象基類的派生類的對象的組成部分,甚至不能創(chuàng)建抽象類型Disc_item的對象。

模板編程

函數(shù)模板

template <typename T>  int compare(const T &v1, const T &v2) {  if (v1 < v2) return -1;  if (v2 < v1) return 1;  return 0; } 

使用compare(1, 2)

類模板

template <class Type> class Queue  { public:  Queue (); // default constructor  Type &front (); // return element from head of Queue  const Type &front () const;  void push (const Type &); // add element to back of Queue  void pop(); // remove element from head of Queue  bool empty() const; // true if no elements in the Queue  private:  // ... };

使用Queue qi;


操作符重載

輸出操作符

輸出操作符通常是非成員函數(shù),定義成類的友元

friend ostream& operator<<(ostream& out, const Sales_item& s) {  out << s.isbn << "\t" << s.units_sold << "\t"  << s.revenue << "\t" << s.avg_price();  return out; }

算術和關系操作

算術和關系操作符定義為非成員函數(shù)

為了與內(nèi)置操作符保持一致,加法返回一個右值,而不是一個引用。

Sales_item operator+(const Sales_item& lhs, const Sales_item& rhs) {  Sales_item ret(lhs); // copy lhs into a local object that we'll  ret += rhs; // add in the contents of rhs  return ret; // return ret by value } int operator<(const TableIndex2D& right) const; friend bool operator== (const UEContext& info1,const UEContext& info2) const {  if(info1.ContextID != info2.ContextID) return false;  return true;  friend bool operator!= (const UEContext& info1,const UEContext& info2) const {  return !(info1 == info2); }

復制控制

包括,一個拷貝構造函數(shù),一個賦值運算符,一個析構函數(shù),一對取址運算符

如果你這么寫:class Empty{};

和你這么寫是一樣的:

class Empty  {  public:  Empty(); // 缺省構造函數(shù)  Empty(const Empty& rhs); // 拷貝構造函數(shù)  ~Empty(); // 析構函數(shù) ---- 是否  // 為虛函數(shù)看下文說明  Empty& operator=(const Empty& rhs); // 賦值運算符  Empty* operator&(); // 取址運算符  const Empty* operator&() const; }; Empty(const Empty& rhs) {  a = rhs.a }


類賦值操作符必須是類的成員,以便編譯器可以知道是否需要合成一個, 賦值必須返回對 *this 的引用。

一般而言,賦值操作符與復合賦值操作符應返回操作符的引用

Guti& Guti::operator=( const Guti& rhs ) {  mtmsi_m = rhs.mtmsi_m;  mmeCode_m = rhs.mmeCode_m;  mmeGid_m = rhs.mmeGid_m;  plmnId_m = rhs.plmnId_m;  return *this; }; 注意,檢查對自己賦值的情況 c& c::operator=(const c& rhs) {  // 檢查對自己賦值的情況  if (this == &rhs) return *this;  ... }

構造函數(shù)初始化式

初始化const對象和引用對象的唯一機會。P389 C++ Primer 5th


協(xié)議

RTP/RTSP/RTCP

RTP協(xié)議RFC1889和RFC3550 G711 PCMU

HTTP

new操作

動態(tài)分配數(shù)組int *pia = new int[10]; // array of 10 uninitialized ints

釋放分配的數(shù)組 delete [] pia;

new數(shù)組

int *arr = new int[1024] delte [] a # 堆上new 對象 class MyClass {  MyClass(int a) {};  int empty() {return 0;}; }; MyClass *p = new MyClass(1); delete p; # 棧上分配 對象 MyClass test(1);

放置式new

區(qū)分以下幾種操作符號:

new operator-普通的new關鍵字

operator new-僅僅申請內(nèi)存返回void*

placement new-在指定內(nèi)存調(diào)用構造函數(shù)初始化類

new [] operator-如果是類對象,會在首部多申請4字節(jié)內(nèi)存用于保存對象個數(shù)

深入探究 new 和 delete

https://blog.csdn.net/codedoctor/article/details/76187567

當我們使用關鍵字new在堆上動態(tài)創(chuàng)建一個對象A時,比如 A* p = new A(),它實際上做了三件事:

向堆上申請一塊內(nèi)存空間(做夠容納對象A大小的數(shù)據(jù))(operator new)

調(diào)用構造函數(shù) (調(diào)用A的構造函數(shù)(如果A有的話))(placement new)

返回正確的指針

當然,如果我們創(chuàng)建的是簡單類型的變量,那么第二步會被省略。

當我們delete的時候也是如此,比如我們delete p 的時候,其行為如下:

定位到指針p所指向的內(nèi)存空間,然后根據(jù)其類型,調(diào)用其自帶的析構函數(shù)(內(nèi)置類型不用)

然后釋放其內(nèi)存空間(將這塊內(nèi)存空間標志為可用,然后還給操作系統(tǒng))

將指針標記為無效(指向NULL)

https://blog.csdn.net/rain_qingtian/article/details/14225211

void* p=::operator new (sizeof(Buffer)); //創(chuàng)建一塊內(nèi)存;冒號表示全局的new Buffer* bp= start_cast<Buffer*>(p); //指針進行裝換 Buffer* buf3=new(bp) Buffer(128); //把bp指針指向的內(nèi)存租借buf3, buf3->put('c'); buf3->~Buffer(); //這里析構函數(shù)要顯示調(diào)用 ::operator delete(p);

放置new構造對象數(shù)組

在棧上分配類內(nèi)存:https://www.cnblogs.com/weekbo/p/8533368.html

new與malloc區(qū)別

b. new和malloc最大區(qū)別: new會調(diào)用類的構造函數(shù),malloc不會;

c. delete和free同理;new/delete是運算符,malloc/free函數(shù)。所以new/delete效率應該會高點。

Linux IPC機制匯總

管道

 #include  無名管道: int pipe(int pipedes[2]) 有名管道:int mkfifo(const char *pathname, mode_t mode)


消息隊列

#include  int msgget(key_t key, int msgflg) //創(chuàng)建 int msgctl(int msqid, int cmd, struct msqid_ds *buf) //設置/獲取消息隊列的屬性值 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) //發(fā)送消息到消息隊列(添加到尾端) ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) //接收消息


共享內(nèi)存

#include  int shmget(key_t key, size_t size, int shmflg) //創(chuàng)建一個共享內(nèi)存空間 int shmctl(int shmid, int cmd, struct shmid_ds *buf) //對共享內(nèi)存進程操作,包括:讀取/設置狀態(tài),刪除操作 void *shmat(int shmid, const void *shmaddr, int shmflg) //將共享內(nèi)存空間掛載到進程中 int shmdt(const void *shmaddr) //將進程與共享內(nèi)存空間分離 **(****只是與共享內(nèi)存不再有聯(lián)系,并沒有刪除共享內(nèi)存****)**


信號

#include


手動實現(xiàn)strcpy

char *strcpy(char *strDest, const char *strSrc) {  if ( strDest == NULL || strSrc == NULL)  return NULL ;  if ( strDest == strSrc)  return strDest ;  char *tempptr = strDest ;  while( (*strDest++ = *strSrc++) != /0)  return tempptr ; }


C++對象內(nèi)存布局

這部分詳細內(nèi)容可以參考《深度探索C++對象模型》

虛函數(shù)多態(tài)機制

通過虛表指針訪問虛成員函數(shù),對普通成員函數(shù)的訪問區(qū)別于虛成員函數(shù)。具體如下:

virtual member function虛成員函數(shù)normalize()的調(diào)用實際上轉(zhuǎn)換成:

(*ptr->vpter[1])(ptr)

函數(shù)指針也有差別,下面第一個是普通函數(shù)指針或者static member function。第二個是non-static member function成員函數(shù)指針。


免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉