2013-01-07 30 views
41

Trong tiêu chuẩn C++ 11, tôi không hiểu lý do tại sao lấy địa chỉ của nullptr không được phép trong khi một được phép lấy địa chỉ của trường hợp std :: nullptr_t của riêng chúng. Ngoài thực tế là nullptr là một từ khóa dành riêng, có bất kỳ lý do được chỉ định nào cho quyết định này không?Tại sao bạn không thể lấy địa chỉ của nullptr?

Đơn giản bởi vì nó cực kỳ phấn khích tôi, tôi đã cố gắng đi vòng quanh hạn chế này với các chức năng sau:

decltype(nullptr)* func(const decltype(nullptr) &nref) noexcept 
{ 
    return const_cast<decltype(nullptr)*>(reinterpret_cast<const decltype(nullptr)*>(&nref)); 
} 

tôi đã phải sử dụng reinterpret_cast trên tham số bởi vì không có nó tôi đã nhận được báo lỗi cuồng loạn:

error: invalid conversion from 'std::nullptr_t*' to 'std::nullptr_t*' [-fpermissive] 

Khi tôi gọi hàm này bằng cách chuyển trực tiếp nullptr mỗi lần tôi nhận được một địa chỉ khác. Có phải nullptr được gán động một địa chỉ đúng lúc để so sánh hay không? Hoặc (có lẽ nhiều khả năng hơn) có lẽ là trình biên dịch buộc một bản sao tạm thời của đối tượng cơ bản? Tất nhiên không ai trong số này là thông tin quan trọng, tôi chỉ thấy nó thú vị lý do tại sao hạn chế cụ thể này được thực hiện (và sau đó tại sao tôi thấy hành vi của tôi).

+22

'nullptr' là giá trị chính xác. Bạn không thể lấy địa chỉ của những người đó. 1 cho thông báo lỗi, mặc dù. – chris

Trả lời

78

Cũng giống như không thể lấy địa chỉ của 5 mặc dù bạn có thể lấy địa chỉ của số int sau khi đặt giá trị 5. Không quan trọng là không có giá trị thay thế cho số nullptr_t.

Giá trị không có địa chỉ; các đối tượng làm.

Một đối tượng tạm thời được tạo khi bạn chuyển giá trị đó đến tham số const & hoặc liên kết giá trị với tham chiếu const, chẳng hạn như static_cast< T const & >(…) hoặc khai báo tham chiếu có tên T const & foo = …;. Địa chỉ bạn đang xem là địa chỉ tạm thời.

+2

Cảm ơn! Tôi đã thực sự đào bới xung quanh một chút và tôi tình cờ gặp [câu trả lời này cho một câu hỏi liên quan] (http://stackoverflow.com/questions/6664115/is-nullptr-not-a-special-keyword-and-an-object -of-stdnullptr-t/6664283 # 6664283). Sau đó tôi nhận ra rằng ** nullptr ** được dự định là một con trỏ rỗng, đúng không? Nó có ý nghĩa rằng bạn sẽ không thể lấy địa chỉ của một chữ. :) –

+18

Có, 'nullptr' là một từ khóa đại diện cho một chữ. Cũng giống như 'true' và' false' (và bạn cũng không thể làm '& true'). – aschepler

+0

Yup! : D Tôi nghĩ rằng khi tôi đang đọc "null pointer _constant_" Tôi đã đọc nó đơn giản là "_logical_ constant" thay vì "_literal_ constant". –

10

nullptr là hằng số (theo nghĩa đen) và không có địa chỉ bộ nhớ, giống như bất kỳ hằng số nào khác trong mã của bạn. Nó tương tự như 0, nhưng thuộc loại đặc biệt std::nullptr_t thay vì void* để tránh các sự cố với quá tải (con trỏ so với số nguyên).

Nhưng nếu bạn xác định biến của riêng mình với giá trị nullptr, nó có địa chỉ bộ nhớ, vì vậy bạn có thể lấy địa chỉ của nó.

Cùng giữ cho bất kỳ liên tục đen khác (mà trong C++ sụp đổ theo thể loại prvalue) của bất kỳ loại nào khác, vì hằng đen không lưu trữ trong chương trình của bạn (chỉ như là một phần của biểu thức nơi chúng xảy ra), đó là lý do tại sao nó không có ý nghĩa gì để nói về địa chỉ. Tuy nhiên, hằng số biến số không có địa chỉ, để chỉ ra sự khác biệt.

27

Nếu bạn sau một câu trả lời tiêu chuẩn, § 18,2/9 đặt quan sát của bạn khá thẳng thừng:

Although nullptr’s address cannot be taken, the address of another nullptr_t object that is an lvalue can be taken.

Ngoài ra, § 2.14.7 nói này về nullptr:

The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t.

Vì vậy, một prvalue là gì? § 3.10/1 câu trả lời rằng:

A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue. — end example ]

Hy vọng rằng, cố gắng để lấy địa chỉ của bất kỳ những điều đó trong ví dụ này sẽ có ý nghĩa hơn là tại sao bạn không thể lấy địa chỉ của nullptr. Đó là một phần của những ví dụ đó!

+0

Cảm ơn thông tin hữu ích! –

+2

Ah, tôi đã không biết prvalue là gì cho đến bây giờ, +1. –

+1

@SethCarnegie, tôi thích định nghĩa của chúng. Đôi khi tôi đi qua tiêu chuẩn để xác định đầy đủ một cái gì đó, nó rất nhiều nhắc nhở tôi về đệ quy. – chris

4

Cả hai từ khóa đúng và sai là từ khóa và dưới dạng chữ mà chúng có loại (bool). nullptr là một con trỏ theo kiểu std :: nullptr_t, và nó là một giá trị (bạn không thể lấy địa chỉ của nó bằng cách sử dụng &), cũng nullptr là prvalue, do đó bạn không thể lấy địa chỉ của nó, hằng số theo nghĩa đen không được lưu trữ trong chương trình của bạn.

Không có địa chỉ có ý nghĩa.

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