2008-12-18 2 views

Trả lời

16

C++ chuẩn có này để nói về các hình thức đơn đối tượng (hình thức thường được sử dụng) của các nhà điều hành mới từ <new> tiêu đề:

hành vi bắt buộc:

Return một con trỏ nonnull để phù hợp bộ nhớ được căn chỉnh (3.7.3) hoặc nếu không thì hãy ném một ngoại lệ bad_alloc. Yêu cầu này là ràng buộc trên một phiên bản thay thế của chức năng này.

Hành vi mặc định:

- Thực thi vòng lặp: Trong vòng lặp, hàm đầu tiên cố gắng phân bổ bộ nhớ được yêu cầu. Cho dù nỗ lực liên quan đến một cuộc gọi đến chức năng thư viện chuẩn C không phải là không xác định.

- Trả về con trỏ đến bộ nhớ đã cấp nếu thử thành công. Nếu không, nếu đối số cuối cùng là set_new_handler() là một con trỏ rỗng, hãy ném bad_alloc.

- Nếu không, hàm sẽ gọi hàm new_handler hiện tại (18.4.2.2). Nếu hàm được gọi trả về, vòng lặp lặp lại.

- Vòng lặp kết thúc khi cố gắng phân bổ bộ nhớ được yêu cầu thành công hoặc khi hàm gọi là new_handler không trả lại.

Tiêu chuẩn có rất nhiều thứ khác để nói về toán tử mới và phân bổ bộ nhớ động (rất nhiều điều để nói), nhưng tôi nghĩ danh sách "Hành vi mặc định" tổng hợp các khái niệm cơ bản của toán tử mới tốt.

+1

Có điều gì giống như kích thước của đối tượng được lưu trữ với mới không. Có thể sử dụng nó khi xóa đối tượng bằng cách sử dụng con trỏ – yesraaj

+0

Điều này chắc chắn còn lại để thực hiện và sẽ khác nhau giữa các nền tảng. – Anteru

+0

Điều đó không được chỉ định theo tiêu chuẩn. Thông thường malloc() hoặc một cái gì đó tương tự sẽ được sử dụng và kích thước của khối bộ nhớ sẽ được giữ bằng cách sử dụng cùng một loại kỹ thuật (hoặc giống hệt nhau nếu malloc() được sử dụng). –

0

Phụ thuộc vào nếu nó bị quá tải hay không, nếu bạn xây dựng ứng dụng để gỡ lỗi, nếu bạn đang sử dụng bộ dò tìm rò rỉ bộ nhớ, nếu bạn có loại lược đồ bộ nhớ nào đó, nếu bạn có thứ gì đó giống như bộ thu gom Boehm đánh dấu/bỏ đánh dấu các bit, v.v., nó có thể làm rất nhiều thứ tùy chỉnh bên trong, hoặc không có gì đặc biệt cả.

+0

Tôi nghĩ rằng anh ấy đã bảo vệ điều đó bằng cách nêu rõ "Chuẩn" –

9

Tôi đã viết giải thích về những gì nó làm trong câu trả lời this. Nó giải thích cách

  • new được bộ nhớ
  • new xử lý thất bại nhớ
  • new xử lý ngoại lệ constructor
  • new xử lý vị trí đặc biệt và nothrow phiên bản

Michael giải thích cách các chức năng cấp phát mặc định (:: toán tử mới) nhận được bộ nhớ độc đáo và cách xử lý lỗi. Tôi đã nhìn thấy câu hỏi của bạn về nơi mà kích thước của một đối tượng được lưu trữ trong ý kiến ​​của mình. Câu trả lời là, không có kích thước được lưu trữ nếu không phải là đại sứ.Hãy nhớ rằng C không cần kích thước cho free (và :: operator mới chỉ có thể sử dụng malloc):

void * memory = malloc(x); 
free (memory); // no need to tell it the size 

Dưới đây là một ví dụ mà bạn thấy cách lưu trữ kích thước có ảnh hưởng đến kích thước của phân bổ cho dưới dạng mảng của một biểu thức mới (không nằm trong câu trả lời khác của tôi):

#include <cstddef> 
#include <iostream> 

struct f { 
    // requests allocation of t bytes 
    void * operator new[](std::size_t t) throw() { 
     void *p = ::operator new[](t); 
     std::cout << "new p: " << p << std::endl; 
     std::cout << "new size: " << t << std::endl; 
     return p; 
    } 

    // requests deleting of t bytes starting at p 
    void operator delete[](void *p, std::size_t t) throw() { 
     std::cout << "delete p: " << p << std::endl; 
     std::cout << "size : " << t << std::endl; 
     return ::operator delete[](p); 
    } 
}; 

int main() { 
    std::cout << "sizeof f: " << sizeof (f) << std::endl; 

    f * f_ = new f[1]; 
    std::cout << "&f_  : " << f_ << std::endl; 
    delete[] f_; 
} 

Nó sẽ in ra một cái gì đó như thế này:

sizeof f: 1 
new p: 0x93fe008 
new size: 5 
&f_  : 0x93fe00c 
delete p: 0x93fe008 
size : 5 

một byt e cho chính đối tượng đó và 4 byte cho số đếm được lưu trữ ngay trước vùng được phân bổ của đối tượng. Bây giờ nếu chúng ta sử dụng chức năng deallocation mà không có một thông số kích thước (chỉ cần loại bỏ nó từ các nhà điều hành xóa), chúng tôi nhận ra điều này:

sizeof f: 1 
new p: 0x9451008 
new size: 1 
&f_  : 0x9451008 
delete p: 0x9451008 

C++ runtime ở đây không quan tâm đến kích thước, vì vậy nó không lưu trữ nó nữa. Lưu ý rằng điều này thực hiện rất cụ thể và đó là những gì gcc thực hiện ở đây để có thể cho bạn biết kích thước trong toán tử thành viên xóa. Các triển khai khác vẫn có thể lưu trữ kích thước và rất có thể nếu có một destructor để gọi cho lớp đó. Ví dụ: chỉ cần thêm ~f() { } ở trên làm cho gcc lưu trữ kích thước, bất kể chúng ta viết hàm deallocation nào.

+0

Bạn có thể giải thích cú pháp cho toán tử 'delete []' này với kích thước khi triển khai pool bộ nhớ, tức là bạn có thể giúp tôi với http://stackoverflow.com/questions/2322742? Cảm ơn! – Tobias