Tôi biết rằng có khá ít câu hỏi C++ (và câu trả lời ở đây trên SO) nói rằng không cần kiểm tra giá trị trả về của biểu thức mới thuần túy cho null, vì đồng bằng mới - biểu hiện cho biết thất bại bằng cách ném ngoại lệ. Về cơ bản họ nói rằng biểu thức mới đơn giản không bao giờ trả về null. (Theo "biểu thức mới thuần túy", tôi có nghĩa là một biểu thức mới không phải là nothrow
một).Toán tử do người dùng định nghĩa mới trả về con trỏ rỗng
Tuy nhiên, mặc dù điều này trông giống như một câu hỏi rất cơ bản, tôi đột nhiên nhận ra rằng tôi không hiểu những giả định cụ thể mà họ đưa ra (nếu có) khi họ đưa ra câu trả lời đó. Cụ thể, tôi tự hỏi liệu tôi có cho phép quá tải dạng đồng bằng cơ bản là ::operator new
để luôn trả về con trỏ null hay không, và do đó, tất cả các biểu thức mới thuần túy sử dụng toán tử đó sẽ trả về con trỏ null.
Theo đặc tả ngôn ngữ, nếu ::operator new
của tôi được khai báo là không ném, khi đó tôi có thể/sẽ cho biết lỗi cấp phát bộ nhớ bằng cách trả về con trỏ rỗng. Vì vậy, hãy thực hiện điều đó
void *operator new(size_t s) throw() {
return 0;
}
int main() {
int *i = new int;
}
Trong các thử nghiệm của tôi, biểu thức mới ở trên sẽ trả về thành công con trỏ rỗng. Vì vậy, tôi có vi phạm bất kỳ quy tắc nào trong đoạn mã trên hay không? Việc khai báo số ::operator new
là không hợp lệ có đúng không?
Và nếu mã ở trên là tốt, thì tôi cho rằng khi ai đó nói rằng "không bao giờ trả về con trỏ rỗng" mới, chúng làm điều đó theo giả định rằng phiên bản tiêu chuẩn do thư viện cung cấp ::operator new
chưa được thay thế. Giả định đó có đúng không?
Có một khía cạnh khác trong cuộc thảo luận này - ngay cả khi tiêu chuẩn cho phép bạn trả về 'nullptr' /' 0' như bạn đã nói, các thư viện chuẩn có cần xử lý '0' không? Tôi muốn đặt cược họ không - và triển khai không - vì vậy nó sẽ là * không thực tế * để viết một chương trình với một toán tử ':: new' trở về 0. Ví dụ: 20.8.9.1/4 yêu cầu 'std :: allocate :: allocate' ném' std :: bad_alloc' nếu lưu trữ không thể nhận được - nó sẽ (thường redundantly) kiểm tra null, hoặc tin tưởng ':: operator new' để ném? –
Phiên bản không phải là phiên bản mới của 'mới' có yêu cầu chữ ký khác không? toán tử 'void * new (std :: size_t size);' không thể trả về một con trỏ null, nó phải ném trong trường hợp lỗi ngay cả khi nó được định nghĩa lại. – user657267
Thư viện chuẩn sẽ sử dụng ':: new T' để xây dựng tiêu chuẩn và' :: new (static_cast (get_allocator() (1)) T' cho vị trí, và các biểu mẫu này luôn gọi hàm phân bổ ném (bất kể là đã được thay thế) –