Bạn có sử dụng NULL hoặc 0 (không) cho con trỏ trong C ++ không?


192

Trong những ngày đầu của C ++ khi nó được bắt đầu trên C, bạn không thể sử dụng NULL vì nó được định nghĩa là (void*)0. Bạn không thể gán NULL cho bất kỳ con trỏ nào khác void*, điều này làm cho nó trở nên vô dụng. Quay lại những ngày đó, người ta chấp nhận rằng bạn đã sử dụng 0(không) cho con trỏ null.

Cho đến ngày nay, tôi vẫn tiếp tục sử dụng số 0 làm con trỏ null nhưng những người xung quanh vẫn khăng khăng sử dụng NULL. Cá nhân tôi không thấy bất kỳ lợi ích nào khi đặt tên ( NULL) cho một giá trị hiện có - và vì tôi cũng muốn kiểm tra các con trỏ như các giá trị thật:

if (p && !q)
  do_something();

sau đó sử dụng số 0 có ý nghĩa hơn (như trong trường hợp bạn sử dụng NULL, bạn không thể sử dụng một cách hợp lý p && !q- bạn cần so sánh rõ ràng với nhau NULL, trừ khi bạn cho NULLlà bằng không, trong trường hợp tại sao lại sử dụng NULL).

Có bất kỳ lý do khách quan nào để thích số 0 hơn NULL (hoặc ngược lại), hay tất cả chỉ là sở thích cá nhân?

Chỉnh sửa: Tôi nên thêm (và có nghĩa là ban đầu nói) rằng với RAII và các ngoại lệ, tôi hiếm khi sử dụng các con trỏ zero / NULL, nhưng đôi khi bạn vẫn cần chúng.


9
chờ đã, không phải là một con trỏ null cần thiết để đánh giá là sai bất kể null có bằng không trong nội bộ hay không?
Vịt Mooing

Câu trả lời:


185

Đây là Stroustrup đảm nhận việc này: Câu hỏi thường gặp về Phong cách và Kỹ thuật của C ++

Trong C ++, định nghĩa NULLlà 0, do đó chỉ có sự khác biệt về mặt thẩm mỹ. Tôi thích tránh các macro, vì vậy tôi sử dụng 0. Một vấn đề khác NULLlà mọi người đôi khi nhầm tưởng rằng nó khác 0 và / hoặc không phải là số nguyên. Trong mã chuẩn, NULLđôi khi / được định nghĩa là một cái gì đó không phù hợp và do đó phải / phải tránh. Điều đó ít phổ biến hơn những ngày này.

Nếu bạn phải đặt tên cho con trỏ null, hãy gọi nó nullptr; đó là những gì nó được gọi trong C ++ 11. Sau đó, nullptrsẽ là một từ khóa.

Điều đó nói rằng, đừng đổ mồ hôi những thứ nhỏ nhặt.


7
Bjarne đã viết điều này trước khi C ++ 0x bắt đầu làm việc với loại null mới. Đây sẽ là trường hợp NULL sẽ được sử dụng cho loại này khi nó có sẵn cho một nền tảng và tôi nghĩ bạn sẽ thấy sự thay đổi C trong sự đồng thuận chung về điều này.
Richard Corden

122

Có một vài lập luận (một trong số đó là tương đối gần đây) mà tôi tin rằng mâu thuẫn với quan điểm của Bjarne về vấn đề này.

  1. Tài liệu về ý định

Việc sử dụng NULLcho phép tìm kiếm khi sử dụng và nó cũng nhấn mạnh rằng nhà phát triển muốn sử dụng một NULLcon trỏ, bất kể nó có được trình biên dịch giải thích NULLhay không.

  1. Quá tải con trỏ và 'int' là tương đối hiếm

Ví dụ mà mọi người trích dẫn là:

void foo(int*);
void foo (int);

void bar() {
  foo (NULL);  // Calls 'foo(int)'
}

Tuy nhiên, ít nhất theo ý kiến ​​của tôi, vấn đề ở trên không phải là chúng ta đang sử dụng NULL cho hằng số con trỏ null, mà là chúng ta có quá tải 'foo', có các loại đối số rất khác nhau. Tham số phải là một intquá, vì bất kỳ loại nào khác sẽ dẫn đến một cuộc gọi mơ hồ và do đó tạo ra một cảnh báo trình biên dịch hữu ích.

  1. Công cụ phân tích có thể giúp NGAY HÔM NAY!

Ngay cả khi không có C ++ 0x, ngày nay vẫn có các công cụ xác minh rằng nó NULLđang được sử dụng cho con trỏ và 0đang được sử dụng cho các loại tích phân.

  1. C ++ 11 sẽ có một std::nullptr_tloại mới .

Đây là đối số mới nhất cho bảng. Vấn đề của 0NULLđang được giải quyết tích cực cho C ++ 0x và bạn có thể đảm bảo rằng đối với mọi triển khai cung cấp NULL, điều đầu tiên họ sẽ làm là:

#define NULL  nullptr

Đối với những người sử dụng NULLchứ không phải là 0, sự thay đổi sẽ là một sự cải tiến trong loại an toàn với ít hoặc không có nỗ lực - nếu bất cứ điều gì nó cũng có thể bắt gặp một vài lỗi mà họ đã sử dụng NULLcho 0. Đối với bất cứ ai sử dụng 0ngày hôm nay .... erm ... cũng hy vọng họ có kiến ​​thức tốt về các biểu thức thông thường ...


1
Đó là một số điểm khá tốt, tôi phải thừa nhận. Tôi rất vui vì C ++ 0x sẽ có loại null, tôi nghĩ rằng nó sẽ làm cho nhiều thứ sạch hơn.
Cướp

2
@Richard, tại sao không làm ngược lại? Bạn có thể sử dụng Meyers nullptr_t sau đó khi 0x có sẵn, bạn gỡ bỏ #includevà giữ an toàn mọi cách.
fnieto - Fernando Nieto

15
#define NULL nullptrcó vẻ nguy hiểm. Để tốt hơn hoặc tồi tệ hơn, rất nhiều mã kế thừa sử dụng NULL cho những thứ khác 0. Ví dụ, các thẻ điều khiển thường được triển khai dưới dạng một số loại tích phân và việc đặt chúng thành NULLkhông phổ biến. Tôi thậm chí đã nhìn thấy các hành vi lạm dụng như sử dụng NULLđể đặt thành một charkẻ hủy diệt bằng không.
Adrian McCarthy

8
@AdrianMcCarthy: Tôi chỉ nói rằng nó nguy hiểm nếu có sự nguy hiểm của mã âm thầm biên dịch và có một ý nghĩa khác. Tôi khá chắc chắn rằng đây không phải là trường hợp, vì vậy trên thực tế, tất cả các cách sử dụng NULL không chính xác sẽ được phát hiện.
Richard Corden

3
@RichardCorden: Ừm, giả định rằng những cách sử dụng khác NULLthực sự không chính xác. Nhiều API đã được sử dụng từ lâu NULLvới các thẻ điều khiển và trên thực tế đó là cách sử dụng tài liệu với nhiều trong số chúng. Thật không thực tế khi đột nhiên phá vỡ những điều đó và tuyên bố rằng họ đang làm sai.
Adrian McCarthy

45

Sử dụng NULL. NULL cho thấy ý định của bạn. Đó là 0 là một chi tiết thực hiện không quan trọng.


28
0 không phải là một chi tiết thực hiện. Tiêu chuẩn định nghĩa 0 là bất cứ mẫu bit nào đại diện cho một con trỏ null.
Ferruccio

5
Như thể .. !! Anh bạn, C ++ là một ngôn ngữ cấp thấp! Sử dụng 0, đó là một thành ngữ nổi tiếng.
hasen

8
Tôi hiểu rằng đó là một phần của tiêu chuẩn. Đây là một chi tiết thực hiện khi đọc mã. Người đọc nên nghĩ "con trỏ NULL" không phải "0 mà trong trường hợp này có nghĩa là con trỏ NULL, không phải là số tôi có thể làm số học với."
Andy Lester

2
+1. Đồng ý với Andy. @Ferruccio, Chi tiết triển khai ý tưởng của lập trình viên không giống như triển khai của trình biên dịch được xác định
người dùng

nếu bạn sử dụng NULL, trong một mã đơn giản không có tiêu đề phức tạp, bạn sẽ thấy lỗi "NULL không được xác định trong phạm vi này" ..
ArtificivelyIntellect

37

Tôi luôn luôn sử dụng:

  • NULL cho con trỏ
  • '\0' cho ký tự
  • 0.0 cho phao và đôi

trong đó 0 sẽ làm tốt Đó là một vấn đề của ý định báo hiệu. Điều đó nói rằng, tôi không phải là hậu môn về nó.


24
ya có lẽ nên sử dụng 0,0F cho số float, để tránh kiểu chữ ngầm
EvilTeach

35

Tôi đã ngừng sử dụng NULL ủng hộ 0 từ lâu (cũng như hầu hết các macro khác). Tôi đã làm điều này không chỉ vì tôi muốn tránh các macro càng nhiều càng tốt, mà còn bởi vì NULL dường như đã được sử dụng quá mức trong mã C và C ++. Nó dường như được sử dụng bất cứ khi nào cần một giá trị 0, không chỉ cho con trỏ.

Trên các dự án mới, tôi đặt điều này trong một tiêu đề dự án:

static const int nullptr = 0;

Bây giờ, khi trình biên dịch tuân thủ C ++ 0x đến, tất cả những gì tôi phải làm là xóa dòng đó. Một lợi ích tuyệt vời của việc này là Visual Studio đã nhận ra nullptr như một từ khóa và làm nổi bật nó một cách thích hợp.


4
Sử dụng NULL sẽ được di động lâu dài hơn. 'nullptr' sẽ có sẵn cho một số nền tảng và không dành cho những nền tảng khác. Giải pháp của bạn ở đây yêu cầu bạn sử dụng bộ tiền xử lý xung quanh khai báo của mình để đảm bảo rằng nó chỉ xuất hiện khi được yêu cầu. NULL sẽ làm điều này tự động.
Richard Corden

6
Tôi không đồng ý. Nó sẽ ít di động hơn trong thời gian ngắn cho đến khi trình biên dịch bắt kịp. Về lâu dài, nó sẽ chỉ là di động và có thể dễ đọc hơn một chút.
Ferruccio

4
Ngoài ra, bạn luôn có thể #define nullptr NULL cho trình biên dịch 0x không C ++ của bạn.
Anteru

20
    cerr << sizeof(0) << endl;
    cerr << sizeof(NULL) << endl;
    cerr << sizeof(void*) << endl;

    ============
    On a 64-bit gcc RHEL platform you get:
    4
    8
    8
    ================

Noi dung chinh cua cau chuyen. Bạn nên sử dụng NULL khi bạn đang xử lý các con trỏ.

1) Nó tuyên bố ý định của bạn (đừng bắt tôi tìm kiếm trong tất cả các mã của bạn đang cố gắng tìm hiểu xem một biến là một con trỏ hoặc một số loại số).

2) Trong các lệnh gọi API nhất định mong đợi các đối số biến, chúng sẽ sử dụng con trỏ NULL để chỉ ra phần cuối của danh sách đối số. Trong trường hợp này, sử dụng '0' thay vì NULL có thể gây ra sự cố. Trên nền tảng 64 bit, cuộc gọi va_arg muốn con trỏ 64 bit, nhưng bạn sẽ chỉ truyền một số nguyên 32 bit. Có vẻ như tôi đang dựa vào 32 bit khác để loại bỏ bạn? Tôi đã thấy một số trình biên dịch nhất định (ví dụ icpc của Intel) không quá duyên dáng - và điều này dẫn đến lỗi thời gian chạy.


NULLcó lẽ không phải là di động, và không an toàn. Có thể có các nền tảng vẫn còn #define NULL 0(theo Câu hỏi thường gặp của Stroustrup: Tôi nên sử dụng NULL hoặc 0? Được trích dẫn bởi câu hỏi hàng đầu và đó là một trong những kết quả tìm kiếm đầu tiên). Ít nhất là trong C ++ cũ hơn, 0có một ý nghĩa khái niệm đặc biệt trong bối cảnh con trỏ. Bạn không nên suy nghĩ cụ thể về bit. Cũng lưu ý rằng trong bối cảnh số nguyên khác nhau ( short, int, long long) " sizeof(0)" sẽ khác nhau. Tôi nghĩ rằng câu trả lời này là một chút sai lầm.
FooF

(Cá nhân là một lập trình viên C trong cuộc sống hàng ngày, tôi đến thăm câu hỏi này để hiểu tại sao mọi người muốn sử dụng NULLthay vì (char *)0, (const char *)0hoặc (struct Boo *)0hoặc (void *)0hoặc bất cứ điều gì để bày tỏ rõ ý định hơn -. Mà không bị (theo ý kiến của tôi) quá cồng kềnh)
FooF

Bỏ phiếu lên. nó đang xảy ra tại trình biên dịch C msvc2013. trong 64 bit, 0 khi chuyển đổi thành con trỏ không đảm bảo là Con trỏ NULL.
pengMiao

16

Nếu tôi nhớ lại chính xác thì NULL được định nghĩa khác trong các tiêu đề mà tôi đã sử dụng. Đối với C, nó được định nghĩa là (void *) 0 và đối với C ++, nó được định nghĩa là chỉ 0. Mã trông giống như:

#ifndef __cplusplus
#define NULL (void*)0
#else
#define NULL 0
#endif

Cá nhân tôi vẫn sử dụng giá trị NULL để biểu diễn các con trỏ null, điều này cho thấy rõ rằng bạn đang sử dụng một con trỏ thay vì một số loại tích phân. Có, bên trong giá trị NULL vẫn là 0 nhưng nó không được biểu thị như vậy.

Ngoài ra, tôi không dựa vào việc chuyển đổi tự động các số nguyên thành các giá trị boolean nhưng so sánh rõ ràng với chúng.

Ví dụ thích sử dụng:

if (pointer_value != NULL || integer_value == 0)

thay vì:

if (pointer_value || !integer_value)

Đủ để nói rằng đây là tất cả các biện pháp khắc phục trong C ++ 11, nơi người ta có thể chỉ cần sử dụng nullptrthay vì NULL, và nullptr_tđó cũng là loại a nullptr.


15

Tôi muốn nói rằng lịch sử đã lên tiếng và những người tranh luận ủng hộ việc sử dụng 0 (không) là sai (bao gồm cả Bjarne Stroustrup). Các lý lẽ ủng hộ 0 chủ yếu là tính thẩm mỹ và "sở thích cá nhân".

Sau khi tạo C ++ 11, với loại nullptr mới, một số trình biên dịch đã bắt đầu phàn nàn (với các tham số mặc định) về việc chuyển 0 đến các hàm với các đối số con trỏ, vì 0 không phải là con trỏ.

Nếu mã được viết bằng NULL, một tìm kiếm và thay thế đơn giản có thể được thực hiện thông qua cơ sở mã để biến nó thành nullptr. Nếu bạn bị mắc kẹt với mã được viết bằng cách sử dụng lựa chọn 0 làm con trỏ thì việc cập nhật nó sẽ tẻ nhạt hơn nhiều.

Và nếu bạn phải viết mã mới ngay bây giờ theo tiêu chuẩn C ++ 03 (và không thể sử dụng nullptr), bạn thực sự chỉ nên sử dụng NULL. Nó sẽ giúp bạn dễ dàng cập nhật hơn trong tương lai.


11

Tôi thường sử dụng 0. Tôi không thích macro và không có gì đảm bảo rằng một số tiêu đề của bên thứ ba mà bạn đang sử dụng không xác định lại NULL là một cái gì đó kỳ lạ.

Bạn có thể sử dụng một đối tượng nullptr theo đề xuất của Scott Meyers và những người khác cho đến khi C ++ nhận được từ khóa nullptr:

const // It is a const object...
class nullptr_t 
{
public:
    template<class T>
    operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template<class C, class T>
    operator T C::*() const   // or any type of null member pointer...
    { return 0; }

private:
    void operator&() const;  // Can't take address of nullptr

} nullptr = {};

Google "nullptr" để biết thêm.


9
Bất kỳ thư viện bên thứ ba nào định nghĩa NULL cho bất kỳ thứ gì khác 0 (hoặc (void*)0nếu được biên dịch dưới dạng mã C) chỉ yêu cầu sự cố và không nên được sử dụng.
Adam Rosenfield

2
Bạn đã bao giờ thực sự thấy một thư viện định nghĩa lại NULL chưa? Không bao giờ? Nếu một thư viện như vậy tồn tại, bạn sẽ gặp vấn đề lớn hơn NULL được xác định lại, chẳng hạn như bạn đang sử dụng một thư viện đủ ngu ngốc để xác định lại NULL.
Andy Lester

1
Hơn một thập kỷ trước, tôi mơ hồ nhớ rằng phải đối phó với một số tiêu đề của bên thứ 3, có thể là Orbix hoặc ObjectStore, đã xác định NULL. Tôi nghĩ rằng tôi có một sự căm ghét bệnh hoạn của các macro sau khi lãng phí nhiều ngày đêm cố gắng để các tiêu đề của bên thứ 3 khác nhau làm việc với windows.h.
jon-hanson

2
"không thích macro" là một bài phê bình kỳ lạ về một #define giống như đối tượng. Có lẽ bạn muốn nói rằng bạn không thích bộ tiền xử lý C?
Andrew Prock

@Andrew - Lợi ích duy nhất của NULLhơn (type *)0là khả năng tìm kiếm, dường như đối với tôi. Mặt khác, nó có vẻ không cần thiết nếu nó không phải là thành ngữ C. Cá nhân tôi nghĩ rằng thành ngữ của việc lan truyền NULLkhắp nơi xứng đáng để chết. NULLlà vĩ mô vô dụng theo ý kiến ​​của tôi. Dao cạo của Occam có một số việc phải làm ở đây ...
FooF

11

Tôi đã từng làm việc trên một máy trong đó 0 là một địa chỉ hợp lệ và NULL được xác định là một giá trị bát phân đặc biệt. Trên máy đó (0! = NULL), vì vậy mã như

char *p;

...

if (p) { ... }

sẽ không làm việc như bạn mong đợi. Bạn phải viết

if (p != NULL) { ... }

Mặc dù tôi tin rằng hầu hết các trình biên dịch định nghĩa NULL là 0 ngày nay nhưng tôi vẫn nhớ bài học từ những năm trước: NULL không nhất thiết phải là 0.


26
Bạn đã không sử dụng một trình biên dịch tuân thủ. Tiêu chuẩn nói NULL 0 và trình biên dịch nên chuyển đổi 0 trong một bối cảnh con trỏ vào một giá trị NULL thật thích hợp cho các vòm.
Evan Teran

17
Vâng, bạn đúng. Đó là vào giữa những năm 80 trước khi ANSI sản xuất một tiêu chuẩn C. Lúc đó không có sự tuân thủ và các nhà văn biên dịch được tự do diễn giải ngôn ngữ khi họ thấy phù hợp. Đó là lý do tại sao một tiêu chuẩn là cần thiết.
mxg

9

Tôi nghĩ rằng tiêu chuẩn đảm bảo rằng NULL == 0, vì vậy bạn có thể làm một trong hai. Tôi thích NULL vì nó ghi lại ý định của bạn.


Nếu bạn có các cấu trúc lồng nhau, tôi nghĩ rằng việc nói foo.bar_ptr = (Bar *) 0thể hiện ý định rõ ràng hơn nhiều foo.bar_ptr = NULL. Thói quen này cũng trao quyền cho trình biên dịch để bắt lỗi hiểu sai cho bạn. Đối với tôi, foo.bar_ptr = 0thể hiện ý định cũng như sử dụng NULLnếu tôi biết đó foo.bar_ptrlà một con trỏ.
FooF

9

Sử dụng 0 hoặc NULL sẽ có tác dụng tương tự.

Tuy nhiên, điều đó không có nghĩa là cả hai đều thực hành lập trình tốt. Cho rằng không có sự khác biệt về hiệu suất, việc chọn một tùy chọn nhận biết ở mức độ thấp so với lựa chọn bất khả tri / trừu tượng là một thực tiễn lập trình tồi. Giúp người đọc mã của bạn hiểu quá trình suy nghĩ của bạn .

NULL, 0, 0.0, '\ 0', 0x00 và tất cả đều dịch sang cùng một thứ, nhưng là các thực thể logic khác nhau trong chương trình của bạn. Chúng nên được sử dụng như vậy. NULL là một con trỏ, 0 là số lượng, 0x0 là một giá trị có bit thú vị, v.v. Bạn sẽ không gán '\ 0' cho một con trỏ cho dù nó có biên dịch hay không.

Tôi biết một số cộng đồng khuyến khích thể hiện kiến ​​thức chuyên sâu về môi trường bằng cách phá vỡ hợp đồng của môi trường. Các lập trình viên có trách nhiệm, tuy nhiên, tạo mã có thể duy trì và giữ các thực hành đó ra khỏi mã của họ.


5

Lạ thay, không ai, kể cả Stroustroup đã đề cập đến điều đó. Trong khi nói chuyện rất nhiều về các tiêu chuẩn và thẩm mỹ không ai nhận thấy rằng nó là nguy hiểm để sử dụng 0trong NULL's Thay vào đó, ví dụ, trong danh sách đối số biến trên kiến trúc nơi sizeof(int) != sizeof(void*). Giống như Stroustroup, tôi thích 0vì lý do thẩm mỹ, nhưng người ta phải cẩn thận không sử dụng nó khi loại của nó có thể mơ hồ.


Và ở những nơi nguy hiểm bạn vẫn có thể sử dụng 0miễn là bạn xác định 0bạn có nghĩa là - ví dụ (int *)0, (char *)0, (const char *)0hoặc (void *)0hoặc (unsigned long long) 0hoặc bất cứ điều gì. Điều này theo tôi thể hiện ý định rõ ràng hơn nhiều NULL.
FooF

1
Chắc chắn, nếu bạn không biết những gì NULLđại diện cho.
Michael Krelin - hacker

Cá nhân tôi thấy hơi khó chịu khi không cần thiết phải sử dụng một cái gì đó (void *)khi tôi có thể sử dụng loại chính xác. Tôi cố tình đưa ra ví dụ về (thường) số nguyên 64 bit trong danh sách vì nó tương tự như trường hợp con trỏ. Hơn nữa, nếu hồi ức của tôi rằng C cũ ++ được định nghĩa NULLnhư 0là chính xác (nó là năm kể từ khi tôi lập trình trong C ++), sau đó chúng ta chứng kiến không có sự cải thiện trong chương trình đúng đắn. Tiêu chuẩn C ++ mới hơn may mắn cung cấp nullptrtừ khóa, vì vậy chúng ta có thể thoát khỏi sự NULLxấu xí này và toàn bộ tranh cãi khi viết C ++ mới hơn.
FooF

Vâng, đó là lý do tại sao việc đúc (void*)đã được trừu tượng hóa NULL. Và NULLthực sự không thể hiện ý định khá rõ ràng hầu hết thời gian. Và tôi nghĩ hồi ức của bạn là sai. Không chắc chắn về các tiêu chuẩn, nhưng trong thực tế tôi tin rằng nó đã được (void*)0. Và yess, nullptrlà một trình chỉnh sửa đẹp, mặc dù nó cũng tương NULLtự - chỉ định null-con trỏ mà không chỉ định loại.
Michael Krelin - hacker

1
@FooF, trên một số nền tảng - có thể. Trong thực tế của tôi, nó hoạt động và do đó tôi nghi ngờ nó được định nghĩa là một con trỏ. Đối với sự mạnh mẽ, vâng, những gì tôi đã cố gắng nói rằng việc sử dụng nullptrthông điệp giống như NULL, điều đó chỉ liên quan đến việc thể hiện ý định mà bạn đề cập ngay từ đầu. (Tiền xử lý NULLtrên gccsản lượng hiện đại __null, bất kể đó là gì).
Michael Krelin - hacker

4

Tôi cố gắng tránh toàn bộ câu hỏi bằng cách sử dụng tài liệu tham khảo C ++ nếu có thể. Thay vì

void foo(const Bar* pBar) { ... }

bạn thường có thể viết

void foo(const Bar& bar) { ... }

Tất nhiên, điều này không phải lúc nào cũng hoạt động; nhưng con trỏ null có thể được sử dụng quá mức.


3

Tôi với Stroustrup về điều này :-) Vì NULL không phải là một phần của ngôn ngữ, tôi thích sử dụng 0.


3

Chủ yếu là sở thích cá nhân, mặc dù người ta có thể đưa ra lập luận rằng NULL làm cho khá rõ ràng rằng đối tượng là một con trỏ hiện không trỏ đến bất cứ thứ gì, ví dụ:

void *ptr = &something;
/* lots o' code */
ptr = NULL; // more obvious that it's a pointer and not being used

IIRC, tiêu chuẩn không yêu cầu NULL là 0, vì vậy sử dụng bất cứ điều gì được xác định trong <stddef.h> có lẽ là tốt nhất cho trình biên dịch của bạn.

Một khía cạnh khác của tranh luận là liệu bạn có nên sử dụng các so sánh logic (truyền ẩn cho bool) hay kiểm tra mức độ khám phá đối với NULL, nhưng điều đó cũng dễ đọc.


3

Tôi thích sử dụng NULL vì nó làm rõ rằng ý định của bạn là giá trị đại diện cho một con trỏ không phải là một giá trị số học. Thực tế rằng đó là một vĩ mô là không may, nhưng vì nó đã ăn sâu vào nó nên có rất ít nguy hiểm (trừ khi ai đó làm điều gì đó thực sự đau đầu). Tôi ước nó là một từ khóa ngay từ đầu, nhưng bạn có thể làm gì?

Điều đó nói rằng, tôi không có vấn đề gì với việc sử dụng con trỏ làm giá trị thật trong chính chúng. Cũng như với NULL, đó là một thành ngữ ăn sâu.

C ++ 09 sẽ thêm cấu trúc nullptr mà tôi nghĩ là đã quá hạn lâu.


1

Tôi luôn luôn sử dụng 0. Không phải vì bất kỳ lý do suy nghĩ thực tế nào, chỉ vì khi tôi mới học C ++, tôi đã đọc một cái gì đó được khuyến nghị sử dụng 0 và tôi luôn luôn làm theo cách đó. Về lý thuyết có thể có một vấn đề nhầm lẫn về khả năng đọc nhưng trong thực tế tôi chưa bao giờ gặp phải một vấn đề như vậy trong hàng ngàn giờ và hàng triệu dòng mã. Như Stroustrup nói, đó thực sự chỉ là vấn đề thẩm mỹ cá nhân cho đến khi tiêu chuẩn trở thành nullptr.


1

Ai đó đã nói với tôi một lần ... Tôi sẽ định nghĩa lại NULL thành 69. Kể từ đó tôi không sử dụng nó: P

Nó làm cho mã của bạn khá dễ bị tổn thương.

Biên tập:

Không phải tất cả mọi thứ trong tiêu chuẩn là hoàn hảo. Macro NULL là hằng số con trỏ null C ++ được xác định thực hiện không tương thích hoàn toàn với macro C NULL, ngoài kiểu ẩn ẩn chuyển đổi nó trong một công cụ vô dụng và dễ bị lỗi.

NULL không hoạt động như một con trỏ null mà là một chữ O / OL.

Cho tôi biết ví dụ tiếp theo không khó hiểu:

void foo(char *); 
void foo(int); 
foo(NULL); // calls int version instead of pointer version! 

Là vì ​​tất cả những điều đó, trong tiêu chuẩn mới xuất hiện std :: nullptr_t

Nếu bạn không muốn chờ đợi tiêu chuẩn mới và muốn sử dụng nullptr, hãy sử dụng ít nhất một tiêu chuẩn đàng hoàng như đề xuất của Meyers (xem bình luận jon.h).


5
NULLlà một phần được xác định rõ của tiêu chuẩn C ++. Để những người thích xác định lại mã chỉnh sửa macro tiêu chuẩn trong dự án của bạn sẽ khiến mã của bạn 'dễ bị tổn thương'; sử dụng NULLkhông.
CB Bailey

1

Vâng, tôi lập luận rằng không sử dụng con trỏ 0 hoặc NULL bất cứ khi nào có thể.

Sử dụng chúng sớm hay muộn sẽ dẫn đến lỗi phân đoạn trong mã của bạn. Theo kinh nghiệm của tôi, và con trỏ trong gereral là một trong những lỗi lớn nhất trong C ++

đồng thời, nó dẫn đến các câu lệnh "if-not-null" trên toàn bộ mã của bạn. Đẹp hơn nhiều nếu bạn có thể dựa vào luôn luôn một trạng thái hợp lệ.

Hầu như luôn luôn có một sự thay thế tốt hơn.


2
Một lỗi phân đoạn được đảm bảo (và nó được đảm bảo trên các hệ thống hiện đại khi bạn hủy đăng ký 0) rất hữu ích cho việc gỡ lỗi. Tốt hơn nhiều so với hội thảo rác ngẫu nhiên và nhận được ai biết kết quả.
Các cuộc đua nhẹ nhàng trong quỹ đạo

-4

Đặt con trỏ về 0 chỉ là không rõ ràng. Đặc biệt nếu bạn đến một ngôn ngữ khác ngoài C ++. Điều này bao gồm C cũng như Javascript.

Gần đây tôi đã delt với một số mã như vậy:

virtual void DrawTo(BITMAP *buffer) =0;

cho chức năng ảo thuần túy lần đầu tiên. Tôi nghĩ rằng đó là một số jiberjash ma thuật trong một tuần. Khi tôi nhận ra, về cơ bản, nó chỉ thiết lập con trỏ hàm thành một null(vì các hàm ảo chỉ là các con trỏ hàm trong hầu hết các trường hợp cho C ++), tôi tự đá mình.

virtual void DrawTo(BITMAP *buffer) =null;

sẽ ít gây nhầm lẫn hơn so với cơ sở đó mà không có khoảng cách thích hợp với đôi mắt mới của tôi. Trên thực tế, tôi tự hỏi tại sao C ++ không sử dụng chữ thường nullgiống như nó sử dụng chữ thường và sai.


Nói chung tôi thích NULl hơn 0 cho con trỏ. Tuy nhiên '= 0;' là cách thành ngữ để khai báo một hàm ảo thuần trong C ++. Tôi thực sự khuyên bạn không nên sử dụng '= NULL;' cho trường hợp cụ thể này
danio

Đây là bình luận hài hước nhất về StackOverflow. Bây giờ bạn có thể đã biết rằng ví dụ bạn đưa ra là một cú pháp cho hàm ảo thuần túy chứ không phải là một con trỏ. Và vâng, @danio đã đúng, bạn không nên sử dụng NULL cho chức năng ảo thuần túy.
sellod
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.