2009-12-21 29 views
14

Tôi có một số lớp mà tôi muốn không cho phép phân bổ heap cho. Nó xảy ra với tôi cuối tuần này mà tôi chỉ có thể tuyên bố điều hành mới tư nhân (và unimplemented) ... Chắc chắn, điều này dẫn đến biên dịch lỗi khi bạn cố gắng mới lớp ... Câu hỏi của tôi là: Có nhiều hơn để điều này? Tôi có thiếu cái gì hay đây là cách tốt để làm những gì tôi muốn?Rõ ràng không cho phép phân bổ đống trong C++

#include <stdio.h> 

class NotOnTheHeap 
{ 
public: 
    NotOnTheHeap() : foo(0) 
    { 
    } 

private: 
    void *operator new(size_t); 
    void operator delete(void*); 
    void *operator new[](size_t); 
    void operator delete[](void*); 

    int foo; 
}; 

class Heapable 
{ 
private: 
    NotOnTheHeap noth; 
}; 

int main(int argc, char* argv[]) 
{ 
    NotOnTheHeap noth; 

    Heapable* heapable = new Heapable; 

    return 0; 
} 
+2

Tại sao bạn muốn hạn chế các lớp này? – GManNickG

+3

@GManNickG Bạn có thể muốn hạn chế nó vì lý do hiệu suất và kiến ​​trúc. Tại sao bạn chắc chắn có thể hướng dẫn các lập trình viên không làm như vậy, nó là tốt để có những thứ tại chỗ * giúp * thực hiện điều này. Vì vậy, vi phạm ngẫu nhiên hoặc vô ý của quy tắc được đánh bắt. Nó có thể đơn giản hơn nếu lớp của bạn có thể thực thi điều này hơn là cố gắng viết một quy tắc phân tích tĩnh để làm như vậy. – iheanyi

Trả lời

11

Phụ thuộc vào ý bạn với "không cho phép phân bổ đống" một cách rõ ràng.

Nếu bạn chỉ muốn ngăn chặn việc phân bổ trực tiếp trên heap, tức là .:

NotOnTheHeap *n = new NotOnTheHeap(); 

nó là đủ tốt. Nhưng nó sẽ không ngăn cản rằng đối tượng của bạn tồn tại trên heap nói chung.

Ví dụ: nó sẽ không ngăn người dùng sử dụng std::vector <NotOnTheHeap>, sẽ phân bổ các đối tượng từ lớp của bạn trên heap.

Nó cũng sẽ không ngăn người dùng sử dụng NotOnTheHeap làm biến thành viên trong một lớp khác, được cấp phát trên heap.

+2

Xác định rõ ràng hàm phân bổ, ':: new A', cũng vẫn hoạt động. –

+1

Vâng, tôi nhận ra điều này ... Đó là lý do tại sao tôi đã "Heapable" trong ví dụ ... Để cho thấy rằng nó vẫn có thể tồn tại trên heap gián tiếp ... – dicroce

0

Bạn không thể chỉ thực hiện toán tử mới một khẳng định (0)?

+22

Tôi nghĩ rằng một lỗi thời gian biên dịch tốt hơn là cho phép mã thực sự biên dịch rồi chết khi chạy. –

+2

Lỗi biên dịch tốt hơn xác nhận. – dicroce

+1

Để chính xác hơn một chút, đây là lỗi thời gian liên kết (vẫn còn thích hợp hơn với lỗi thời gian chạy). –

1

Điều đó chủ yếu sẽ đạt được những gì bạn đang cố gắng.

Giải pháp của bạn không bao gồm ở chỗ mới, có thể có hoặc không có trên đống.

+1

Có thể mở rộng để bao gồm vị trí mới không? – dicroce

+2

Không, vị trí mới không thể thay thế được. Nó chỉ trả về địa chỉ mà nó đã được đưa ra. – GManNickG

+0

Mã như trong câu hỏi đã bao gồm vị trí mới: 'new (some_void_ptr) A' sẽ thất bại.Nó không bao gồm ':: new (some_void_ptr) A' bởi vì khi hàm phân bổ được xác định rõ ràng thì quá tải lớp không được xem xét (áp dụng cho tất cả các biểu mẫu vị trí cũng như không vị trí, ví dụ:' :: new A') . Tôi không chắc tại sao GMan đề cập đến điều này, bởi vì bạn có thể khai báo 'A :: toán tử new (size_t, void *)', v.v., bạn không thể thay thế ':: operator new (size_t, void *)', nhưng mã không bao giờ thay thế toán tử ':: new (size_t)' toàn cục. –

1

Bạn có thể vô hiệu hóa bản sao hoặc thậm chí xây dựng mặc định và toán tử = etc cho một trường hợp nghiêm ngặt hơn (một số trường hợp giá trị nhúng hoặc sử dụng vùng chứa).

Tuy nhiên, điều đó sẽ đưa bạn ra khỏi một số cấu trúc hữu ích và buộc bạn giới thiệu ngữ nghĩa của riêng bạn (cái gì đó dễ thấy hơn trong VM; thiếu/cảm ứng của toán tử tương tự và cơ chế tương đương/bình đẳng). Bạn sẽ có thể thấy một vài cảnh báo trình biên dịch quá, nó sẽ không đi tất cả các cách, nhưng nếu nó an ủi bất kỳ nó có thể có một hoặc hai sử dụng.

-2

Nhận lấy C++ hiệu quả của Scott Meyers và C++ hiệu quả hơn - anh ấy bao gồm loại nội dung này. Mỗi lập trình viên C++ nên sở hữu & đọc những cuốn sách này.

+0

cuốn sách tốt nhưng -1 cho không thực sự trả lời câu hỏi. – ipapadop

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