2011-07-16 42 views
12
int& fun() 
{ 
    int * temp = NULL; 
    return *temp; 
} 

Trong phương pháp trên, tôi đang cố thực hiện dereferencing của con trỏ NULL. Khi tôi gọi hàm này, nó không đưa ra ngoại lệ. Tôi tìm thấy khi trở về loại là bằng cách tham khảo nó không đưa ra ngoại lệ nếu nó là theo giá trị sau đó nó. Ngay cả khi dereferencing của con trỏ NULL được assinged để tham khảo (như dòng dưới đây) sau đó cũng nó không cung cấp cho.Chỉ định tham chiếu theo dereferencing con trỏ NULL

int* temp = NULL: 
int& temp1 = *temp; 

Câu hỏi của tôi là trình biên dịch không thực hiện dereferencing trong trường hợp tham chiếu?

+4

Tài liệu tham khảo được xử lý như con trỏ trong nội bộ chúng khác nhau về cú pháp bạn sử dụng trên chúng. Biết rằng dereferenciation của bạn chỉ "gán" pointervalue để tham chiếu làm cho nó một tham chiếu đến NULL. Điều đó không kích hoạt bất kỳ acces bộ nhớ. Khi bạn quay trở lại theo giá trị, việc dereferenciation sẽ dẫn đến truy cập bộ nhớ ở 0, hầu như luôn mang đến cho bạn một segfault. – Nobody

+0

Kiểm tra bài viết này, giải thích tại sao con trỏ NULL là một tính năng khủng khiếp trong OOP và nên tránh bằng mọi giá: http://www.yegor256.com/2014/05/13/why-null-is-bad.html – yegor256

Trả lời

16

Dereferencing một con trỏ rỗng là Hành vi không xác định.

Hành vi không xác định nghĩa là mọi thứ có thể xảy ra, Vì vậy, không thể xác định hành vi cho việc này.

Phải thừa nhận rằng, tôi sẽ thêm trích dẫn chuẩn C++ này cho lần thứ n, nhưng có vẻ như nó cần phải có.

Về hành vi undefined,

C++ chuẩn phần 1.3.24 trạng thái:

hành vi undefined phép dao động từ phớt lờ tình hình hoàn toàn với kết quả không thể đoán trước, để hành xử trong dịch hoặc thực hiện chương trình trong một tài liệu cách đặc trưng của môi trường (có hoặc không có thông báo chẩn đoán), để chấm dứt một bản dịch hoặc thực hiện (với việc phát hành một thông báo chẩn đoán).

LƯU Ý:
Ngoài ra, chỉ để đưa nó vào thông báo của bạn:
Sử dụng một tham chiếu trả lại hoặc con trỏ đến một biến cục bộ bên trong một hàm cũng là một hành vi undefined. Bạn nên phân bổ con trỏ trên freestore (heap) bằng cách sử dụng mới và sau đó trả về một tham chiếu/con trỏ đến nó.

EDIT:
Như @ James McNellis, thích hợp chỉ ra trong các ý kiến,
Nếu con trỏ trả về hoặc tham chiếu không được sử dụng, hành vi được được xác định rõ.

+0

Có, đồng ý với UB nêu trên. nhưng câu hỏi của tôi là nếu dereferencing của con trỏ NULL hoặc con trỏ NULL không được thực hiện để assinged rằng để tham khảo sau đó không trình biên dịch làm các hoạt động dereferencing? like- Int * t = NULL; Int & t1 = * t; –

+1

@G Mann: Tham chiếu chỉ là một 'bí danh' đối với loại ban đầu mà nó được khởi tạo. Làm thế nào nó được thực hiện là một chi tiết thực hiện các trình biên dịch và tiêu chuẩn không xác định cách nó nên được thực hiện. –

+2

Khi bạn chọn một con trỏ null, mã không hợp lệ và trình biên dịch có thể làm bất cứ thứ gì. Nó không phải là có ý nghĩa để hỏi * tại sao * nó đã làm bất cứ điều gì. –

7

Khi bạn dereference một con trỏ null, bạn không nhất thiết phải nhận được một ngoại lệ; tất cả những gì được đảm bảo là hành vi là không xác định (điều đó thực sự có nghĩa là không có sự đảm bảo nào về hành vi của nó).

Khi biểu thức *temp được đánh giá, không thể lý do về hành vi của chương trình.

+0

Tôi đang thêm cùng một bình luận như tôi đã làm trong bài viết khác- Có, đồng ý trên UB đã đề cập ở trên. nhưng câu hỏi của tôi là nếu dereferencing của con trỏ NULL hoặc con trỏ NULL không được thực hiện để assinged rằng để tham khảo sau đó không trình biên dịch làm các hoạt động dereferencing? like- Int * t = NULL; Int & t1 = * t; –

+0

Đó là trường hợp mà đối với hầu hết các trình biên dịch, trong nhiều trường hợp, một tham chiếu được thực hiện như một con trỏ. Ngoài ra, nó phụ thuộc vào trình biên dịch, cài đặt, v.v. –

+0

Đúng là tôi sai. Trường hợp nó được thực hiện như con trỏ thì trình biên dịch có thể không thực hiện thao tác dereferencing. –

1

Không * con trỏ rỗng, đó là UB.(hành vi không xác định, bạn không bao giờ có thể giả định nó sẽ làm bất cứ điều gì ngắn chiếu sáng con chó của bạn trên lửa và buộc bạn phải shrooms mà sẽ dẫn đến giai thoại FABULOUS)

Một số thông tin và lịch sử của con trỏ null trong họ Algol/C : http://en.wikipedia.org/wiki/Pointer_(computing)#Null_pointer

các ví dụ và ý nghĩa của hành vi undefined: http://en.wikipedia.org/wiki/Undefined_behavior#Examples_in_C

0

tôi không chắc là tôi hiểu những gì bạn đang cố gắng todo. Dereferencing của ** NULL ** con trỏ không được xác định.

Trong trường hợp bạn muốn để cho biết rằng bạn phương pháp không phải lúc nào trả về giá trị bạn có thể khai báo nó như:

bool fun (int val &);

hoặc STL cách (tương tự như std :: bản đồ chèn):

std::pair<int, bool> fun(); 

hoặc tăng chiều:

boost::optional<int> fun(); 
4

Bạn đang không phép dereference một con trỏ null, vì vậy trình biên dịch có thể tạo ra mã giả định rằng bạn không làm điều đó. Nếu bạn làm điều đó anyway, trình biên dịch có thể được tốt đẹp và cho bạn biết, nhưng nó không phải. Đó là một phần của hợp đồng nói rằng bạn không được làm điều đó.

Trong trường hợp này, tôi đặt cược trình biên dịch sẽ là thật tuyệt và cho bạn biết sự cố đã có lúc biên dịch, nếu bạn chỉ đặt mức cảnh báo đúng cách.

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