2010-11-10 39 views
15

tôi thấy mã như thế này:lý do tại sao điều hành cuộc gọi mới một cách rõ ràng

void *NewElts = operator new(NewCapacityInBytes); 

Và cuộc gọi một cách rõ ràng phù hợp operator delete được sử dụng hậu quả sau này.

Tại sao làm điều này thay vì:

void *NewElts = new char[NewCapacityInBytes]; 

Tại sao cuộc gọi rõ ràng để operator newoperator delete ??

+1

Bạn đã đặt dấu ngoặc vuông trên ví dụ thứ hai về mục đích? –

+0

Có lẽ dự định: 'new char [NewCapacityInBytes]' – MSalters

+0

@MSalters: bạn nói đúng, đã sửa – zaharpopov

Trả lời

24

Gọi rõ ràng operator new như vậy gọi là toán tử "thô" toàn cầu mới. Toàn cầu operator new trả về một khối bộ nhớ thô mà không cần gọi hàm tạo của đối tượng hoặc bất kỳ quá tải do người dùng xác định là new. Vì vậy, về cơ bản, toàn cầu operator new cũng tương tự như malloc từ C.

Vì vậy:

// Allocates space for a T, and calls T's constructor, 
// or calls a user-defined overload of new. 
// 
T* v = new T; 

// Allocates space for N instances of T, and calls T's 
// constructor on each, or calls a user-defined overload 
// of new[] 
// 
T* v = new T[N]; 

// Simply returns a raw byte array of `sizeof(T)` bytes. 
// No constructor is invoked. 
// 
void* v = ::operator new(sizeof(T)); 
+2

khi nào điều này hữu ích? – zaharpopov

+6

@zaharpopov: Một ví dụ sẽ được thực hiện một hồ bơi bộ nhớ, nơi bạn phân bổ một đoạn lớn một lần và người dùng của hồ bơi sẽ gọi chức năng tạo các đối tượng trong đoạn, thay vì sử dụng 'mới'. Tùy thuộc vào mẫu phân bổ, điều này có thể cung cấp hiệu suất tốt hơn so với 'mới' và' xóa'. –

+0

Ooo. Hấp dẫn. Tôi không biết về * này * góc của C + +. –

2

Nếu bạn gọi điều hành mới (bytesize), sau đó bạn có thể xóa nó bằng cách sử xóa, trong khi nếu bạn phân bổ qua new char [ bytesize], sau đó bạn phải khớp nó bằng cách sử dụng delete [], đây là một sự hủy bỏ để tránh bất cứ khi nào có thể. Điều này rất có thể là lý do gốc để sử dụng nó.

+1

Làm thế nào nó là một abomination? –

+3

Nếu bạn phân bổ thông qua toán tử 'global new' toàn cục, bạn có thể deallocate nó bằng cách sử dụng toán tử' global delete' toàn cục. Nhưng 'toán tử delete' toàn cục sẽ không gọi hàm hủy. Vì vậy, nếu bạn thực sự xây dựng một đối tượng bằng cách sử dụng vị trí mới sau khi gọi toàn cầu 'toán tử new', thì toàn cục' toán tử delete' không đủ để phá hủy đối tượng. Bạn cũng cần phải gọi destructor một cách rõ ràng trước khi deallocating bộ nhớ. Về cơ bản, cả toán tử 'operator new' và' operator delete' toàn cầu đều cho phép bạn tách phân bổ lưu trữ/deallocation và khởi tạo/hủy đối tượng. –

+0

@Charles: Anh ấy đã không sắp xếp bất cứ điều gì mới, và bộ nhớ đó không cần phá hủy. Là một hình thức phân bổ bộ nhớ hoàn toàn, thì toán tử new() là cược an toàn nhất vì nó không cần kích thích xóa [] hoặc không có gì bất thường() để deallocate. @Steve: delete [] là một abomination vì nó không cần thiết. Nó không giống như, khi bạn sử dụng toán tử mới và không mới [], thì vùng heap đó không cần phải lưu trữ kích thước của khối hay bất cứ thứ gì như thế. – Puppy

6

Nếu bạn viết:

T *p = new T; 

Đó phân bổ đủ bộ nhớ để tổ chức một T, sau đó xây dựng T vào nó. Nếu bạn viết:

T *p = ::operator new(sizeof(T)); 

Đó phân bổ đủ bộ nhớ để tổ chức một T, nhưng không xây dựng T. Một trong những lần bạn có thể thấy đây là khi người ta cũng sử dụng vị trí mới:

T *p = ::operator new(sizeof(T)); // allocate memory for a T 
new (p) T; // construct a T into the allocated memory 
p->~T(); // destroy the T again 
::operator delete(p); // deallocate the memory 
1

Sử dụng nó khi bạn muốn cấp phát một khối bộ nhớ "thô" và không muốn bất kỳ thứ gì được tạo trong bộ nhớ đó.

Có rất ít sự khác biệt thực tế giữa việc phân bổ một khối bộ nhớ thô và "xây dựng" một mảng ký tự nhưng sử dụng toán tử mới rõ ràng báo hiệu ý định của bạn cho bất kỳ ai đọc mã quan trọng.

Các vấn đề liên quan