2010-08-30 26 views
7

Tôi có dưới đoạn mãCó cần thiết để quá tải vị trí nhà điều hành mới, khi chúng tôi quá tải nhà điều hành mới?

class Test 
{ 
public: 
    Test(){} 
    Test(int i) {} 

    void* operator new (size_t size) 
    { 
     void *p = malloc(size); 
     return p; 
    } 
    //void* operator new (size_t size, Test *p) 
    //{ 
    // return p; 
    //} 
}; 

int main() { 
    Test *p = new Test; 
    int i = 10; 
    new(p) Test(i); 
} 

Trên đoạn mã không biên dịch trong visual studio, trừ khi tôi bỏ ghi chú ra vị trí quá tải chức năng điều hành mới. Nếu tôi nhận xét bình thường quá tải mới, trong trường hợp đó cũng nó hoạt động tốt. Việc quá tải vị trí mới bắt buộc khi quá tải toán tử mới bình thường (Nếu vị trí mới cần được sử dụng cho lớp đó)

Mã liên quan xóa vị trí không được hiển thị tại đây.

Trả lời

3

Thường thì không, vì nó không thường được sử dụng. Nhưng nó có thể là cần thiết, kể từ khi bạn quá tải operator new trong một lớp, nó ẩn tất cả các quá tải của toàn cầu ::operator new.

Vì vậy, nếu bạn muốn sử dụng vị trí mới trên các đối tượng của lớp đó, hãy làm; nếu không thì không. Tương tự với nothrow mới.

Nếu bạn vừa thay đổi sơ đồ phân bổ và bạn ngạc nhiên khi ai đó đang sử dụng vị trí mới sau lưng, đó có thể là điều cần điều tra trước khi áp dụng băng trợ giúp này.

Nếu lớp được sử dụng trong các thùng chứa thư viện chuẩn, không trực tiếp với new, lược đồ phân bổ tùy chỉnh phải được định nghĩa bởi lớp Allocator, không phải là quá tải. Phân bổ mặc định std::allocator không tôn trọng thành viên operator new quá tải, nhưng bỏ qua chúng. Xem bên dưới.


Disclaimer: đẳng cấp phạm vi operator new quá tải chủ yếu là hữu ích để gỡ lỗi, và thậm chí sau đó nó khó khăn để có được ngữ nghĩa đáng tin cậy có ý nghĩa. Cẩn thận:

  • Bạn cũng cần quá tải operator delete. (Không được thực hiện trong ví dụ trong câu hỏi này.)

  • Quá tải sẽ bị bỏ qua theo cú pháp đủ điều kiện ::new T. Bạn không thể ngăn chặn việc bỏ qua như vậy. Đây là cách mà std::allocator<T> phân bổ mọi thứ. Bạn có thể chuyên std::allocator cho các loại của bạn, nhưng đó là một số cách vào lỗ thỏ đã.

  • Đối với mỗi ::operator new quá tải được giới thiệu bởi bất kỳ thư viện, trong đó có vị trí kinh điển mới từ <new>, bạn sẽ phải xem xét liệu nó áp dụng cho lớp học của bạn và quyết định có thêm một tình trạng quá tải, hoặc đấu tranh với sự thất bại của không đủ tiêu chuẩn new biểu thức.

  • Đối với mỗi ::operator new bạn áp dụng vào lớp học của mình, bạn phải cung cấp vị trí thành viên tương ứng operator delete với ngữ nghĩa chính xác. Điều này được gọi trong trường hợp constructor thoát khỏi ngoại lệ. Không có nó sẽ dẫn đến rò rỉ bộ nhớ chỉ trong những trường hợp rất cụ thể, trong một hồ bơi có thể bị hạn chế về tài nguyên.

Tóm lại, thành viên operator new là điểm phản đối mã hóa phòng thủ.

+0

Thực ra, tốt nhất là nên triển khai vị trí và không phát hiện 'mới' bất cứ khi nào bạn triển khai tuỳ chỉnh' mới' vì lý do này. Bạn có thể ngắt mã hiện tại bằng cách không cung cấp sáu phiên bản mới và xóa (đừng quên các biểu mẫu mảng). –

+0

vị trí 'mới' không thường được sử dụng trong mã, nhưng các container STL thường xuyên sử dụng nó để tách phân bổ bộ nhớ của chúng khỏi việc xây dựng đối tượng của chúng. –

+0

@Philip: Đó là một lá cờ đỏ sau đó, vì 'std :: allocator' lấy bộ nhớ của nó từ' :: operator new'. Trong trường hợp đó, giải pháp là triển khai một trình phân bổ tùy chỉnh, không phải để kích hoạt một tiêu chuẩn. – Potatoswatter

1

Vị trí toán tử mới không tồn tại theo mặc định cho một lớp để khi bạn thực hiện cuộc gọi tới new(p) Test(i); Trình biên dịch C++ không thể tìm thấy định nghĩa của hàm đã nhận xét trong ví dụ trên. Nếu bạn bỏ ghi chú cho toán tử vị trí mới cho lớp của bạn, và bình luận cho toán tử "bình thường" thì toán tử mới "bình thường" mặc định sẽ được sử dụng và mã của bạn sẽ biên dịch.

0

triển khai std :: _ Xây dựng sử dụng toàn cầu vị trí mới. Vì vậy, mối quan tâm về khả năng tương thích STL không phải là mối quan tâm. Tuy nhiên, lo ngại về phá vỡ mã hiện tại, có thể đã được viết

new ((void*)p) thing;

hơn

::new ((void*)p) thing;

chắc chắn là một điểm hợp lệ.

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