深入剖析c++中new的用法

一、c++中new關鍵字的概述

new關鍵字是c++中用來動態地分配內存空間的操作符。使用new運算符可以在程序運行時從堆(heap)中分配內存空間,而delete運算符則可以釋放這些空間。

與傳統的申請棧內存相比,new有以下幾個優點:

1.分配的堆空間大小可以在程序運行時改變,有極大的靈活性;

2.分配的空間可以在程序運行期間多次使用;

3.分配的空間不會隨著函數調用的結束而自動釋放。

二、c++中new的基本用法

c++中new的基本語法是:new typename、new (placement)typename,它們的使用方法分別如下:

//第一種語法,不需要指定放置位置
int *p = new int;
delete p;

//第二種語法中,placement表示分配空間的位置,後接();
//typename表示要分配空間的類型,可以是任何類型,也可以是帶有參數的構造函數
void *address = malloc(sizeof(int));
int *p = new (address) int;
delete p;

需要注意的是,使用第二種語法時需要保證地址值是「允許的」,即剛好可以存儲T對象。

三、c++中new運算符的直接和替代定位操作

在c++中,new運算符不僅可以用於分配單個對象的內存空間,還可以分配數組和實例化類的內存空間。

1.分配單個對象的內存空間:

//分配單個對象的內存空間
int *p = new int;
*p = 1;
delete p;

2.分配一維數組的內存空間:

//分配一維數組
int *p = new int[10];
for(int i=0; i<10; i++){
    p[i] = i;
}
delete[] p;

3.分配二維數組的內存空間:

//分配二維數組
int **p = new int*[10];
for(int i=0; i<10; i++){
    p[i] = new int[10];
    for(int j=0; j<10; j++){
        p[i][j] = i*j;
    }
}
//釋放二維數組
for(int i=0; i<10; i++){
    delete[] p[i];
}
delete[] p;

4.實例化類的內存空間:

//實例化類
class Person{
public:
    int age;
    string name;
    Person(int _age, string _name): age(_age), name(_name){}
};
Person *p = new Person(18, "Tom");
cout<age<<endl;
cout<name<<endl;
delete p;

除了直接使用new運算符外,還可以使用new替代定位操作符,用於分配一段內存空間,並且不用初始化這些對象。其語法為:new (address) typename[N] 。該操作符主要用於一些需要特殊內存管理的應用中,如用於構造對象池或預分配內存池等。例如:

int* block = new int [100];
// 一次性從block分配內存10個int對象  
int* pointer = new (block) int [10]; 
//獲取只能在該內存塊中使用的指針,指向內存池的開端
int* base_ptr = pointer;

//將指針向前移動1個int的位元組
base_ptr++;
//移動指針指向的位置,操作對象的時候也可以簡化語法
pointer[1] = 20;
//將指針向後移動3個int的位元組
pointer += 3;
pointer[0] = 10;

//隨後在該對象池中使用重新分配內存方式來動態構造更多對象。
//這裡不再推薦使用new替代定位操作符
delete[] block;

四、c++中new運算符性能的提升

c++中,頻繁的使用malloc和free會嚴重影響程序的性能,而new和delete的效率要高得多。一個常見的做法是使用定長內存池,利用new在堆中分配一段內存,然後在內存上以小塊形式對外分配,這樣能同時保證內存使用的效率和堆空間的不浪費。實現方法如下:

class MemoryPoll{
public:
    MemoryPoll(int blocksize = 1024);
    ~MemoryPoll();
    void* allocate();
    void free(void* block);
private:
    MemoryPoll(const MemoryPoll&);
    MemoryPoll& operator = (const MemoryPoll &);
    void expand_();

    int blocksize_;
    char *pool_start_;
    char *pool_end_;
    char *free_start_;
};
MemoryPoll::MemoryPoll(int blocksize){
    blocksize_ = blocksize;
    pool_start_ = new char[blocksize_];
    pool_end_ = pool_start_ + blocksize_;
    free_start_ = pool_start_;
}
MemoryPoll::~MemoryPoll(){
    delete[] pool_start_;
}
void* MemoryPoll::allocate(){
    if (free_start_==pool_end_) { expand_(); }
    void* result = free_start_;
    free_start_ += sizeof(int);
    return result;
}
void MemoryPoll::free(void* block){
    *(reinterpret_cast(block)) = *(int*)pool_start_;
    *(int*)pool_start_ = (int)block;
}
void MemoryPoll::expand_(){
    int head = (int)blocksize_;
    pool_start_ = new char[head + blocksize_];
    pool_end_ = pool_start_ + blocksize_;
    *(int*)pool_start_ = head;
    free_start_ = pool_start_ + head;
}
MemoryPoll mp;
void* operator new(size_t size){
    return mp.allocate();
}
void operator delete (void* ptr, size_t size){
    mp.free(ptr);
}
int main(){
    //利用重載的new和c++容器實現整形數組的分配和銷毀
    vector<int, allocator > a;
    for(int i=0; i<10; i++){
        a.push_back(i);
    }
    system("pause");
    return 0;
}

五、c++中new運算符的使用要點

使用new運算符時應注意以下幾個問題:

1.使用new分配內存後,需要手動釋放內存,否則會造成內存泄漏;

2.使用new分配內存時,必須保證內存空間足夠,否則會造成內存溢出;

3.在使用new分配內存後,需要在不再使用時立即釋放內存,否則可能導致系統資源緊張;

4.new運算符無法保證線程安全性,因此在多線程環境下使用需要手動管理。

以上是c++中new的用法介紹,希望對讀者有所幫助。

原創文章,作者:LYGIB,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/363868.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
LYGIB的頭像LYGIB
上一篇 2025-03-12 18:48
下一篇 2025-03-12 18:48

相關推薦

  • Python中new和init的區別

    new和init都是Python中常用的魔法方法,它們分別負責對象的創建和初始化,本文將從多個角度詳細闡述它們的區別。 一、創建對象 new方法是用來創建一個對象的,它是一個類級別…

    編程 2025-04-29
  • JavaScript中使用new Date轉換為YYYYMMDD格式

    在JavaScript中,我們通常會使用Date對象來表示日期和時間。當我們需要在網站上顯示日期時,很多情況下需要將Date對象轉換成YYYYMMDD格式的字元串。下面我們來詳細了…

    編程 2025-04-27
  • 如何使用return new crontrigger(cron).nextexecutiontime(triggercontext)實現定時調度

    如果你正在尋找一種可靠且簡單的方式來實現定時調度,那麼你可能需要了解return new crontrigger(cron).nextexecutiontime(triggerco…

    編程 2025-04-27
  • 深入解析Vue3 defineExpose

    Vue 3在開發過程中引入了新的API `defineExpose`。在以前的版本中,我們經常使用 `$attrs` 和` $listeners` 實現父組件與子組件之間的通信,但…

    編程 2025-04-25
  • 深入理解byte轉int

    一、位元組與比特 在討論byte轉int之前,我們需要了解位元組和比特的概念。位元組是計算機存儲單位的一種,通常表示8個比特(bit),即1位元組=8比特。比特是計算機中最小的數據單位,是…

    編程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什麼是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一個內置小部件,它可以監測數據流(Stream)中數據的變…

    編程 2025-04-25
  • 深入探討OpenCV版本

    OpenCV是一個用於計算機視覺應用程序的開源庫。它是由英特爾公司創建的,現已由Willow Garage管理。OpenCV旨在提供一個易於使用的計算機視覺和機器學習基礎架構,以實…

    編程 2025-04-25
  • 深入了解scala-maven-plugin

    一、簡介 Scala-maven-plugin 是一個創造和管理 Scala 項目的maven插件,它可以自動生成基本項目結構、依賴配置、Scala文件等。使用它可以使我們專註於代…

    編程 2025-04-25
  • 深入了解LaTeX的腳註(latexfootnote)

    一、基本介紹 LaTeX作為一種排版軟體,具有各種各樣的功能,其中腳註(footnote)是一個十分重要的功能之一。在LaTeX中,腳註是用命令latexfootnote來實現的。…

    編程 2025-04-25
  • 深入理解Python字元串r

    一、r字元串的基本概念 r字元串(raw字元串)是指在Python中,以字母r為前綴的字元串。r字元串中的反斜杠(\)不會被轉義,而是被當作普通字元處理,這使得r字元串可以非常方便…

    編程 2025-04-25

發表回復

登錄後才能評論