2012-06-21 33 views
6

Tôi chỉ đang cố gắng biên dịch một dự án lớn hơn một chút bằng cách sử dụng Visual Studio 2012 Release Candidate, C++. Dự án đã được/được biên dịch bằng cách sử dụng VS2010 ngay bây giờ. . (Tôi chỉ tham lam để có được C++ 11 điều, vì vậy tôi cố gắng :)Tại sao bad_alloc (const char *) được tạo riêng tư trong Visual C++ 2012?

Ngoài những điều mà tôi có thể giải thích bởi bản thân mình, dự án sử dụng mã như thế này:

ostringstream ostr; 
ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ")."; 
throw bad_alloc(ostr.str().c_str()); 

Các trình biên dịch bây giờ than phiền

error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared 
    in class 'std::bad_alloc' 

... điều này là đúng. Phiên bản của hàm tạo đó giờ đây là riêng tư.

Lý do khiến phiên bản của hàm tạo đó là riêng tư? Được khuyến nghị bởi C++ 11 tiêu chuẩn không sử dụng constructor đó với đối số?

(Tôi có thể tưởng tượng rằng nếu phân bổ thất bại, nó có thể gây ra nhiều vấn đề hơn để cố gắng xây dựng bất cứ điều gì mới. Tuy nhiên, nó chỉ là tôi đoán.)

Cảm ơn, Petr

Trả lời

14

C++ 11 Tiêu chuẩn xác định bad_alloc như vậy (18.6.2.1):

class bad_alloc : public exception { 
public: 
    bad_alloc() noexcept; 
    bad_alloc(const bad_alloc&) noexcept; 
    bad_alloc& operator=(const bad_alloc&) noexcept; 
    virtual const char* what() const noexcept; 
}; 

Không có hàm tạo chuỗi. Một nhà cung cấp cung cấp một nhà xây dựng như vậy sẽ làm cho mã sử dụng nó không di động, vì các nhà cung cấp khác không có nghĩa vụ cung cấp nó.

Tiêu chuẩn C++ 03 xác định tập hợp các nhà xây dựng tương tự, vì vậy VS không tuân thủ phần này của tiêu chuẩn ngay cả trước C++ 11. MS cố gắng để làm cho VS như là tiêu chuẩn phù hợp nhất có thể, vì vậy họ đã có thể chỉ cần sử dụng dịp (mới VS, tiêu chuẩn mới) để sửa chữa một không tương thích.

Edit: Bây giờ tôi đã nhìn thấy mã VS2012, nó cũng là rõ ràng lý do tại sao các nhà xây dựng đề cập còn lại tin, thay vì được loại bỏ hoàn toàn: có vẻ là chỉ có một sử dụng constructor đó, trong lớp bad_array_new_length . Vì vậy, bad_array_new_length được khai báo là friend trong bad_alloc và do đó có thể sử dụng hàm tạo riêng đó. Sự phụ thuộc này có thể tránh được nếu bad_array_new_length chỉ lưu trữ tin nhắn trong con trỏ được sử dụng bởi what(), nhưng nó không có nhiều mã.

+0

Cảm ơn rất nhiều câu trả lời được xây dựng. – pepr

1

Nếu bạn quen với việc truyền tải thông điệp khi bạn ném tiêu chuẩn :: bad_alloc, một kỹ thuật phù hợp là xác định lớp nội bộ bắt nguồn từ std :: bad_alloc và ghi đè ‘what’ để cung cấp thông điệp thích hợp.

Bạn có thể đặt lớp công khai và gọi hàm tạo trực tiếp hoặc tạo hàm trợ giúp, chẳng hạn như throw_bad_alloc, lấy thông số (và thông tin vô hướng bổ sung) và lưu trữ chúng trong lớp nội bộ.

Thư không được định dạng cho đến khi ‘what’ được gọi. Bằng cách này, thư giãn có thể giải phóng một số bộ nhớ để thư có thể được định dạng với lý do thực tế (cạn kiệt bộ nhớ, kích thước yêu cầu xấu, tham nhũng đống, v.v.) tại trang bắt. Nếu định dạng không thành công, chỉ cần gán và trả về một tin nhắn tĩnh.

Trimmed dụ:

(Mẹo:. Các nhà xây dựng bản sao chỉ có thể gán _Message để nullptr, chứ không phải là sao chép các tin nhắn vì thông điệp được định dạng theo yêu cầu Các nhà xây dựng di chuyển, tất nhiên chỉ có thể tịch thu nó :-) .

class internal_bad_alloc: public std::bad_alloc 
    { 
    public: 
     // Default, copy and move constructors.... 

     // Assignment constructor... 
     explicit internal_bad_alloc(int errno, size_t size, etc...) noexcept: 
     std::bad_alloc() 
     { 
     // Assign data members... 
     } 

     virtual ~internal_bad_alloc(void) noexcept 
     { 
     // Free _Message data member (if allocated). 
     } 

     // Override to format and return the reason: 
     virtual const char* what(void) const noexcept 
     { 
     if (_Message == nullptr) 
      { 
      // Format and assign _Message. Assign the default if the 
      // format fails... 
      } 
     return _Message; 
     } 

    private: 
     // Additional scalar data (error code, size, etc.) pass into the 
     // constructor and used when the message is formatted by 'what'... 
     mutable char* _Message; 
     static char _Default[]; 
    } 
}; 

// 
// Throw helper(s)... 
// 
extern void throw_bad_alloc(int errno, size_t size, etc...) 
    { 
    throw internal_bad_alloc(errno, size, etc...); 
    } 
Các vấn đề liên quan