亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

More Effective C++:不同new和delete

2019-11-17 05:38:37
字體:
來源:轉載
供稿:網友

  人們有時似乎喜歡故意使C++語言的術語難以理解。比如說new操作符(new Operator)和operator new的區別。

  當你寫這樣的代碼:

string *ps = new string("Memory Management");
  你使用的new是new操作符。這個操作符就象sizeof一樣是語言內置的,你不能改變它的含義,它的功能總是一樣的。它要完成的功能分成兩部分。第一部分是分配足夠的內存以便容納所需類型的對象。第二部分是它調用構造函數初始化內存中的對象。new操作符總是做這兩件事情,你不能以任何方式改變它的行為。

  你所能改變的是如何為對象分配內存。new操作符調用一個函數來完成必需的內存分配,你能夠重寫或重載這個函數來改變它的行為。new操作符為分配內存所調用函數的名字是operator new。

  函數operator new 通常這樣聲明:

void * operator new(size_t size);
  返回值類型是void*,因為這個函數返回一個未經處理(raw)的指針,未初始化的內存。(假如你喜歡,你能寫一種operator new函數,在返回一個指針之前能夠初始化內存以存儲一些數值,但是一般不這么做。)參數size_t確定分配多少內存。你能增加額外的參數重載函數operator new,但是第一個參數類型必須是size_t。(有關operator new更多的信息參見Effective C++ 條款8至條款10。)

  你一般不會直接調用operator new,但是一旦這么做,你可以象調用其它函數一樣調用它:

void *rawMemory = operator new(sizeof(string));
  操作符operator new將返回一個指針,指向一塊足夠容納一個string類型對象的內存。

  就象malloc一樣,operator new的職責只是分配內存。它對構造函數一無所知。operator new所了解的是內存分配。把operator new 返回的未經處理的指針傳遞給一個對象是new操作符的工作。當你的編譯器遇見這樣的語句:

string *ps = new string("Memory Management");
  它生成的代碼或多或少與下面的代碼相似(更多的細節見Effective C++條款8和條款10,還有我的文章Counting object里的注釋。):

void *memory = // 得到未經處理的內存
operator new(sizeof(string)); // 為String對象
call string::string("Memory Management") //初始化
on *memory; // 內存中

// 的對象

string *ps = // 是ps指針指向
static_cast<string*>(memory); // 新的對象
  注重第二步包含了構造函數的調用,你做為一個程序員被禁止這樣去做。你的編譯器則沒有這個約束,它可以做它想做的一切。因此假如你想建立一個堆對象就必須用new操作符,不能直接調用構造函數來初始化對象。

  Placement new

  有時你確實想直接調用構造函數。在一個已存在的對象上調用構造函數是沒有意義的,因為構造函數用來初始化對象,而一個對象僅僅能在給它初值時被初始化一次。但是有時你有一些已經被分配但是尚未處理的的(raw)內存,你需要在這些內存中構造一個對象。你可以使用一個非凡的operator new ,它被稱為placement new。

  下面的例子是placement new如何使用,考慮一下:

class Widget {
 public:
  Widget(int widgetSize);
  ...
};

Widget * constrUCtWidgetInBuffer(void *buffer,

int widgetSize)
{
 return new (buffer) Widget(widgetSize);
}
  這個函數返回一個指針,指向一個Widget對象,對象在轉遞給函數的buffer里分配。當程序使用共享內存或memory-mapped I/O時這個函數可能有用,因為在這樣程序里對象必須被放置在一個確定地址上或一塊被例程分配的內存里。(參見條款4,一個如何使用placement new的一個不同例子。)

  在constructWidgetInBuffer里面,返回的表達式是:

new (buffer) Widget(widgetSize)

  這初看上去有些生疏,但是它是new操作符的一個用法,需要使用一個額外的變量(buffer),當new操作符隱含調用operator new函數時,把這個變量傳遞給它。被調用的operator new函數除了待有強制的參數size_t外,還必須接受void*指針參數,指向構造對象占用的內存空間。這個operator new就是placement new,它看上去象這樣:

void * operator new(size_t, void *location)
{
 return location;
}
  這可能比你期望的要簡單,但是這就是placement new需要做的事情。究竟operator new的目的是為對象分配內存然后返回指向該內存的指針。在使用placement new的情況下,調用者已經獲得了指向內存的指針,因為調用者知道對象應該放在哪里。placement new必須做的就是返回轉遞給它的指針。(沒有用的(但是強制的)參數size_t沒有名字,以防止編譯器發出警告說它沒有被使用;見條款6。) placement new是標準C++庫的一部分。為了使用placement new,你必須使用語句#include <new>(或者假如你的編譯器還不支持這新風格的頭文件名)。

  讓我們從placement new回來片刻,看看new操作符(new operator)與operator new的關系,你想在堆上建立一個對象,應該用new操作符。它既分配內存又為對象調用構造函數。假如你僅僅想分配內存,就應該調用operator new函數;它不會調用構造函數。假如你想定制自己的在堆對象被建立時的內存分配過程,你應該寫你自己的operator new函數,然后使用new操作符,new操作符會調用你定制的operator new。假如你想在一塊已經獲得指針的內存里建立一個對象,應該用placement new。

  Deletion and Memory Deallocation

  為了避免內存泄漏,每個動態內存分配必須與一個等同相反的deallocation對應。函數operator delete與delete操作符的關系與operator new與new操作符的關系一樣。當你看到這些代碼:


string *ps;
...
delete ps; // 使用delete 操作符
  你的編譯器會生成代碼來析構對象并釋放對象占有的內存。

  Operator delete用來釋放內存,它被這樣聲明:

void operator delete(void *memoryToBeDeallocated);
  因此, delete ps;

  導致編譯器生成類似于這樣的代碼:

ps->~string(); // call the object's dtor
operator delete(ps); // deallocate the memory

// the object occupied
  這有一個隱含的意思是假如你只想處理未被初始化的內存,你應該繞過new和delete操作符,而調用operator new 獲得內存和operator delete釋放內存給系統:

void *buffer = // 分配足夠的
operator new(50*sizeof(char)); // 內存以容納50個char

//沒有調用構造函數

...
operator delete(buffer); // 釋放內存

// 沒有調用析構函數
  這與在C中調用malloc和free等同。

  假如你用placement new在內存中建立對象,你應該避免在該內存中用delete操作符。因為delete操作符調用operator delete來釋放內存,但是包含對象的內存最初不是被operator new分配的,placement new只是返回轉遞給它的指針。誰知道這個指針來自何方?而你應該顯式調用對象的析構函數來解除構造函數的影響:

// 在共享內存中分配和釋放內存的函數 void * mallocShared(size_t size);

void freeShared(void *memory);
void *sharedMemory = mallocShared(sizeof(Widget));
Widget *pw = // 如上所示,
constructWidgetInBuffer(sharedMemory, 10); // 使用

// placement new

...
delete pw; // 結果不確定! 共享內存來自
// mallocShared, 而不是operator new

pw->~Widget(); // 正確。 析構 pw指向的Widget,

// 但是沒有釋放
//包含Widget的內存

freeShared(pw); // 正確。 釋放pw指向的共享內存

// 但是沒有調用析構函數
  如上例所示,假如傳遞給placement new的raw內存是自己動態分配的(通過一些不常用的方法),假如你希望避免內存泄漏,你必須釋放它。(參見我的文章Counting objects里面關于placement delete的注釋。)

  Arrays

  到目前為止一切順利,但是還得接著走。到目前為止我們所測試的都是一次建立一個對象。怎樣分配數組?會發生什么?

string *ps = new string[10]; // allocate an array of
// objects
  被使用的new仍然是new操作符,但是建立數組時new操作符的行為與單個對象建立有少許不同。第一是內存不再用operator new分配,代替以等同的數組分配函數,叫做operator new[](經常被稱為array new)。它與operator new一樣能被重載。這就答應你控制數組的內存分配,就象你能控制單個對象內存分配一樣(但是有一些限制性說明,參見Effective C++ 條款8)。

 ?。╫perator new[]對于C++來說是一個比較新的東西,所以你的編譯器可能不支持它。假如它不支持,無論在數組中的對象類型是什么,全局operator new將被用來給每個數組分配內存。在這樣的編譯器下定制數組內存分配是困難的,因為它需要重寫全局operator new。這可不是一個能輕易接受的任務。缺省情況下,全局operator new處理程序中所有的動態內存分配,所以它行為的任何改變都將有深入和普遍的影響。而且全局operator new有一個正常的簽名(normal signature)(也就單一的參數size_t,參見Effective C++條款9),所以假如你 決定用自己的方法聲明它,你馬上使你的程序與其它庫不兼容基于這些考慮,在缺乏operator new[]支持的編譯器里為數組定制內存治理不是一個合理的設計。)

  第二個不同是new操作符調用構造函數的數量。對于數組,在數組里的每一個對象的構造函數都必須被調用:

string *ps = // 調用operator new[]為10個
new string[10]; // string對象分配內存,

// 然后對每個數組元素調用
// string對象的缺省構造函數。
  同樣當delete操作符用于數組時,它為每個數組元素調用析構函數,然后調用operator delete來釋放內存。

  就象你能替換或重載operator delete一樣,你也替換或重載operator delete[]。在它們重載的方法上有一些限制。請參考優秀的C++教材。

  new和delete操作符是內置的,其行為不受你的控制,凡是它們調用的內存分配和釋放函數則可以控制。當你想定制new和delete操作符的行為時,請記住你不能真的做到這一點。你只能改變它們為完成它們的功能所采取的方法,而它們所完成的功能則被語言固定下來,不能改變。(You can modify how they do what they do, but what they do is fixed by the language)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线www| 久久精品国产亚洲精品| 日韩电影中文字幕在线观看| 亚洲精品suv精品一区二区| 成人黄色生活片| 97精品久久久| 国产精品女人网站| 岛国av一区二区| 韩曰欧美视频免费观看| 国产精品看片资源| 日韩中文视频免费在线观看| 国内揄拍国内精品| 亚洲综合av影视| 欧美亚洲激情在线| 亚洲一区二区三区四区在线播放| 欧美性视频在线| 中文字幕视频一区二区在线有码| 少妇高潮久久久久久潘金莲| 国产一区二区三区免费视频| 国产精品久久久久久av下载红粉| 成人国产精品久久久| 欧美激情高清视频| 亚洲欧洲在线免费| 91亚洲精品在线| 欧美在线视频一区| 欧美亚洲在线播放| 丝袜美腿亚洲一区二区| 欧美激情精品久久久久久久变态| 精品中文字幕在线2019| 成人在线精品视频| 美女视频黄免费的亚洲男人天堂| 欧美高清videos高潮hd| 成人精品一区二区三区电影黑人| 国产成人jvid在线播放| 欧美性生交xxxxx久久久| 51精品国产黑色丝袜高跟鞋| 欧美午夜视频一区二区| 欧美老肥婆性猛交视频| 亚洲福利视频网站| 欧美xxxx综合视频| 亚洲欧美日韩视频一区| 亚洲国产天堂网精品网站| 日本中文字幕不卡免费| 国产精品中文字幕在线观看| 91a在线视频| 狠狠久久五月精品中文字幕| 欧美日韩精品在线| 精品亚洲aⅴ在线观看| 成人国内精品久久久久一区| 日韩欧美有码在线| 尤物99国产成人精品视频| 久久久久久噜噜噜久久久精品| 亚洲综合中文字幕68页| 国产精品日日摸夜夜添夜夜av| 亚洲影院在线看| 久久中国妇女中文字幕| 午夜精品久久17c| 国产福利精品视频| 国产99久久精品一区二区永久免费| 国产成人精品av在线| 国产精品ⅴa在线观看h| 欧美成年人视频| 成人免费大片黄在线播放| 色爱精品视频一区| 国产中文字幕91| 久久综合五月天| 国产啪精品视频网站| 九九久久精品一区| 日韩三级影视基地| 欧美视频一区二区三区…| 正在播放亚洲1区| 在线日韩欧美视频| 深夜福利91大全| 日韩精品视频三区| 亚洲精选一区二区| 视频在线观看一区二区| 日韩欧美精品中文字幕| 美女福利视频一区| 欧美日韩国产丝袜美女| 久久国产精品久久久久久| 精品国偷自产在线| 91人人爽人人爽人人精88v| 亚洲欧美国产日韩中文字幕| 亚洲自拍另类欧美丝袜| 日韩在线一区二区三区免费视频| 亚洲国产欧美一区二区丝袜黑人| 久久视频在线观看免费| 色噜噜国产精品视频一区二区| 色哟哟入口国产精品| 欧美成人高清视频| 国产精品av免费在线观看| 欧美理论电影在线播放| 国内精品中文字幕| 欧美午夜片欧美片在线观看| 成人福利免费观看| 欧美日韩在线免费观看| 欧美日韩视频免费播放| 国产成人久久久精品一区| 亚洲毛茸茸少妇高潮呻吟| 色诱女教师一区二区三区| 免费不卡欧美自拍视频| 亚洲一区精品电影| 日韩av电影在线播放| 中文字幕精品视频| 日韩av片免费在线观看| 91禁外国网站| 欧美亚洲在线播放| 国产97免费视| 97精品国产97久久久久久| 国产精品久久久久久久久借妻| www日韩中文字幕在线看| 久久国产精品首页| 国产精品久久久久久婷婷天堂| 亚洲日本欧美日韩高观看| 日韩美女在线播放| 日韩精品黄色网| 久色乳综合思思在线视频| 亚洲国产精品久久91精品| 欧美日韩国产丝袜另类| 黑人巨大精品欧美一区二区一视频| 亚洲黄色av网站| 国产精品久久久久久久天堂| 久久久久久久久爱| 欧美日韩国产在线| 亚洲精品美女免费| 欧美日本中文字幕| 国产精品最新在线观看| 亚洲第一精品夜夜躁人人爽| 欧美大片在线免费观看| 亚洲xxxx在线| 精品欧美激情精品一区| 亚洲男人的天堂在线| 日韩精品福利在线| 日韩免费观看高清| 91精品国产综合久久男男| 日韩精品免费在线观看| 亚洲二区在线播放视频| 欧美日韩亚洲系列| 中文字幕亚洲一区二区三区五十路| 亚洲成人国产精品| 欧美高清视频在线| 亚洲精品中文字幕有码专区| 欧美不卡视频一区发布| 欧美日韩成人免费| 欧洲日本亚洲国产区| 亚洲精品久久久久中文字幕欢迎你| 日韩精品免费在线视频观看| 久久久www成人免费精品| 亚洲国产天堂久久国产91| 538国产精品一区二区免费视频| 久久这里有精品视频| 国产精品视频免费观看www| 91在线免费看网站| 91久久精品国产91久久| 成人亚洲欧美一区二区三区| 国产亚洲欧美日韩精品| 尤物九九久久国产精品的特点| 亚洲国产精品福利| 色偷偷888欧美精品久久久| 欧美黄色三级网站| 国产香蕉一区二区三区在线视频| 九九热最新视频//这里只有精品| zzijzzij亚洲日本成熟少妇| 亚洲欧美一区二区三区在线|