程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> CPP之內存分配,cpp分配

CPP之內存分配,cpp分配

編輯:C++入門知識

CPP之內存分配,cpp分配


new & delete expression

1. Introduction

 

A new expression allocates and constructs an object of a specified type.

A new[] expression allocates and constructs an array of objects.

These expressions use the corresponding version of the library operator new functions to allocate raw memory in which the expression constructs an object or array of the specified type.

1. new 表達式分配和構造特定類型的對象。

2. new[] 表達式分配和構造對象數組。

3. 這些表達式使用庫函數 operator new 的對應版本分配原始內存,並在該內存中構造特定類型的對象或數組。

 

A delete expression destroys a dynamically allocated object of a specified type and frees the memory used by that object.

A delete[] expression destroys the elements of a dynamically allocated array of a specified type and frees the memory used by the array.

These expressions use the corresponding version of the library or class-specific operator delete functions to free raw memory that held the object or array.

1. delete 表達式銷毀特定類型的動態分配對象,並釋放該對象所用的內存。

2. delete[] 表達式銷毀特定類型動態分配數組的元素,並釋放該數組所使用的內存。

3. 這些表達式使用庫函數或類特定的 operator delete 函數的對應版本來釋放保存對象或數組的原始內存。

2. How to work?

我們來看看 newdelete 表達式是如何工作的。例如,使用如下 new 表達式:

 

// new expression

string * sp = new string("initialized");

實際上發生了以下步驟:

 

首先,該表達式調用名為 operator new 的標准庫函數,分配足夠大的原始的未類型化的內存,以保存指定類型的一個對象;

接下來,運行該類型的一個構造函數,用指定初始化式構造對象;

最後,返回指向新分配並構造的對象的指針。

當使用如下 delete 表達式時:

 

delete sp;

將會刪除堆上分配的對象,發生以下兩個步驟:

 

首先,對 sp 指向的對象運行適當的析構函數;

然後,通過調用名為 operator delete 的標准庫函數釋放該對象所用內存。

operator new and operator delete Functions

1. The operator new and operator delete Interface

operator newoperator delete 函數有兩個重載版本(一個拋異常,一個不拋異常),每個版本支持相關的 new 表達式和 delete 表達式:

 

void *operator new(size_t);        // allocate an object

void *operator new[](size_t);      // allocate an array

void *operator delete(void*);      // free an object

void *operator delete[](void*);    // free an array

雖然 operator newoperator delete 函數的設計意圖是供 new 表達式使用,但它們也是標准庫中的可用函數。我們可以使用它們來獲得未構造的原始內存,它們有點類似 allocate 類的 allocatordeallocate 成員。

2. allocator and deallocate

std::allocator::allocate

pointer allocate (size_type n, allocator<void>::const_pointer hint=0);

Allocate block of storage

Attempts to allocate a block of storage with a size large enough to contain n elements of member type value_type (an alias of the allocator's template parameter), and returns a pointer to the first element.
The storage is aligned appropriately for objects of type value_type, but they are not constructed.
In the standard default allocator, the block of storage is allocated using ::operator new one or more times, and throws bad_alloc if it cannot allocate the total amount of storage requested.

分配原始內存空間,參數 n 填要分配的元素的個數,返回值是指向新分配的對象的指針。

Parameters

n
Number of elements (each of size sizeof(value_type)) to be allocated.
        The member type size_type is an alias of size_t (in the standard default allocator) size_t is an unsigned integral
type.
 
hint
Either 0 or a value previously obtained by another call to allocate and not yet freed with deallocate.
        When it is not 0, this value may be used as a hint to improve performance by allocating the new block near the
one specified. The address of an adjacent element is often a good choice.
(hint如果不是默認值0,可以填寫之前 allocate 返回的指針,這可以在一定程度上提高性能)
Return value

A pointer to the initial element in the block of storage.

pointer and const_pointer are member types (defined as aliases of T* and const T* respectively in std::allocator<T>).

The standard default allocator throws bad_alloc if it cannot allocate the requested amount of storage.

 

std::allocator::deallocate

void deallocate (pointer p, size_type n);

Release block of storage

Releases a block of storage previously allocated with member allocate and not yet released.
The elements in the array are not destroyed by a call to this member function.
In the default allocator, the block of storage is at some point deallocated using ::operator delete (either during the function call, or later).

回收 p 指向的“可容納 n 個元素”的內存空間

3. Placement new Expressions

1. 標准庫函數 operator newoperator deleteallocatorallocatedeallocate 成員的低級版本,它們都分配但不初始化內存。

2. allocator 的成員 construct(執行對象的構造函數)destroy(執行對象的析構函數) 也有兩個低級選擇,這些成員在由 allocator 對象分配的空間中初始化和銷毀對象。

3. 類似於 construct 成員,有第三種 new 表達式,稱為定位 new定位 new 表達式在已分配的原始內存中初始化一個對象,它與 new 的其他版本的不同之處在於,它不分配內存。相反,它接受指向已分配但未構造內存的指針,並在該內存中初始化一個對象。實際上,定位 new 表達式使我們能夠在特定的、預分配的內存地址構造一個對象。

operator new

throwing (1)

void* operator new (std::size_t size) throw (std::bad_alloc);

nothrow (2)

void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();

placement (3)

void* operator new (std::size_t size, void* ptr) throw();
其中第三種形式即為定位 new。

定位 new 表達式的形式是:

 new (place_address) type
 new (place_address) type (initializer-list)
 
返回值:place_address

其中 place_address 必須是一個指針,而 initializer-list 提供了(可能為空的)初始化列表,以便在構造新分配的對象時使用。

定位 new 表達式比 allocator 類的 construct 成員更靈活。定位 new 表達式初始化一個對象的時候,它可以使用任何構造函數,並直接建立對象。construct 函數總是使用拷貝構造函數。

例如,可以用下面兩種方式之一,從一對迭代器初始化一個已分配但未構造的 string 對象:

     allocator<string> alloc;
     
     string *sp = alloc.allocate(2); // allocate space to hold 2 strings
     
     // two ways to construct a string from a pair of iterators
     new (sp) string(b, e);                    // construct directly in place
     alloc.construct(sp + 1, string(b, e));   // build and copy a temporary

定位 new 表達式使用了接受一對迭代器的 string 構造函數,在 sp 指向的空間直接構造 string 對象。而當調用 construct 函數的時候,必須首先從迭代器構造一個 string 對象(臨時對象),以獲得傳遞給 constructstring 對象,然後,該函數使用 string 的拷貝構造函數,將匿名臨時 string 對象復制到 sp 指向的對象中。

通常,這些區別是無關緊要的:例如對於值型類而言,在適當的位置直接構造對象與構造臨時對象並進行復制之間沒有太大差別,並且性能差別也微乎其微。

但對某些類而言,使用拷貝構造函數是不可能的(因為復制構造函數是私有的),或者是應該避免的,在這種情況下,也許有必要使用定位 new 表達式來直接構造對象。

小結

1.

C++中的new運算符,具體工作流程如下:

1.調用標准庫函數operator new申請原始內存

2.調用place new表達式,執行類的構造函數

3.返回內存地址

而delete操作符的工作是:

1.調用對象的析構函數

2.調用標准庫函數operator delete釋放內存

2.

分配原始內存的三種手段:

1. 使用malloc

2. 使用operator new

3. allocator的allocate函數

這三者從上到下,是一個由低級到高級的過程。

實際上標准庫函數 allocate 就是通過標准庫函數 operator new 實現,而 operator new 通常也是通過 malloc 來實現。

執行構造函數,有兩種手段:

1. 使用placement new運算符

2. 使用allocator的construct函數

實際上標准庫函數 construct 的內部就是通過 placement new 來實現的


在C++的class類中,要分配一塊大的內存,該怎操作?

lcyasdlcy的回答是正確的。
一般類的聲明放在.h中,類的實現放在.cpp中。

什麼是變量的聲明,什麼是變量的定義?
變量聲明:int a; // 此時不分配內存
變量定義:int a = 20; // 此時分配內存

一般C++類中頭文件是聲明一個變量,CPP中去初始化這個變量。
-------------------------------.h文件------------------------------------
class A
{
private:
BYTE* middle_buffer;
}

-----------------------------.cpp文件-----------------------------------
class A
{
A()
{
middle_buffer = new BYTE[1024*1024*3*3] ;
}
}

正常是這樣用的。
還有一種就是靜態變量,這個變量是可以直接初始化的,
class A
{
private:
static BYTE* middle_buffer = new BYTE[1024*1024*3*3] ;
}
一般標准做法還是在頭文件中聲明,在CPP中定義。
-------------------------------.h文件------------------------------------
class A
{
private:
static BYTE* middle_buffer;
}

-----------------------------.cpp文件-----------------------------------
BYTE* middle_buffer = new BYTE[1024*1024*3*3] ;
class A
{
}
 

// c++動態分配內存cpp : Defines the entry point for the console application

while(ncount == nsize -1)
{
nsize++ ;
char *ptemp = new char[nsize] ;
StrCpy(ptemp , p) ;
delete[] p ;
p = ptemp ;
}
ptemp,作用域只限於while循環語句,while結束後,不得使用
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved