2013-08-13 46 views
30

Tôi biết rằng static_assert xác nhận thời gian biên dịch và assert - vào thời gian chạy, nhưng sự khác biệt trong thực tế là gì? Theo như tôi hiểu, trong sâu thẳm họ là những mẩu mã, nhưSự khác biệt giữa khẳng định và static_assert là gì?

if (condition == false) exit(); 
  • Ai đó có thể cho tôi một ví dụ về nơi chỉstatic_assert sẽ làm việc, hoặc chỉassert?
  • Họ có làm bất cứ điều gì một tuyên bố đơn giản if không thể làm gì?
  • Thực tiễn không tốt để sử dụng chúng?
+0

'static_assert' là khai báo, được xây dựng bằng ngôn ngữ chính. Nó không mở rộng đến bất cứ điều gì bởi vì nếu nó không thành công, việc biên dịch dừng lại. – jrok

+4

@KerrekSB Tôi đã hỏi ** ba ** câu hỏi rõ ràng, hãy dành thời gian đọc chúng trước khi đưa ra giả định – Oleksiy

+1

Bạn sử dụng khẳng định để xác định rằng có lỗi trong logic lập trình của bạn và nó phải được sửa trong mã. một 'if' được sử dụng để phân nhánh giữa các đường logic khác nhau trong mã. Đây là một sự khác biệt lớn – Default

Trả lời

35

Bạn đặt ba câu hỏi, vì vậy tôi sẽ cố gắng trả lời từng câu hỏi.

  • Ai đó có thể cho tôi một ví dụ về nơi chỉstatic_assert sẽ làm việc, hoặc chỉassert?

static_assert là tốt để kiểm tra logic trong mã của bạn lúc biên dịch. assert là tốt cho việc kiểm tra một trường hợp trong thời gian chạy mà bạn mong đợi sẽ luôn luôn có một kết quả, nhưng có lẽ bằng cách nào đó có thể tạo ra một kết quả bất ngờ trong các tình huống bất ngờ.Ví dụ: bạn chỉ nên sử dụng assert để xác định xem con trỏ được chuyển vào phương thức là null khi có vẻ như không bao giờ xảy ra. static_assert sẽ không bắt được điều đó.

  • Họ có thể làm bất cứ điều gì một tuyên bố đơn giản if không thể làm gì?

assert thể được sử dụng để phá vỡ thực hiện chương trình, vì vậy bạn có thể sử dụng một if, một thông báo lỗi thích hợp, và sau đó dừng thực hiện chương trình để có được một hiệu ứng tương tự, nhưng assert là một chút đơn giản cho trường hợp đó. static_assert tất nhiên chỉ hợp lệ để phát hiện vấn đề biên dịch trong khi if phải có giá trị theo chương trình và không thể đánh giá cùng kỳ vọng tại thời gian biên dịch. (An if có thể được sử dụng để nhổ ra một thông báo lỗi tại thời gian chạy, tuy nhiên.)

  • Việc sử dụng chúng có tệ không?

Không hề!

+0

Câu trả lời hay, tuy nhiên, thêm khẳng định đó (biến thể thời gian chạy) chỉ hoạt động trong các bản dựng gỡ lỗi và là một noop trong bản phát hành có lẽ là một ý tưởng hay. Điều này có thể tốt, trên một tuyên bố if, với thử nghiệm gỡ lỗi rộng rãi, để loại bỏ một số lỗi thừa có thể có khi kiểm tra tối ưu hóa cho các bản phát hành bản phát hành. Cũng là một cảnh báo để xem xét không đặt logic thay đổi trạng thái trong dấu ngoặc đơn, vì logic kết quả sẽ không tồn tại trong bản phát hành ... do đó với khẳng định (x ++ <12) chẳng hạn, x ++ wont tồn tại trong bản phát hành, chỉ trong gỡ lỗi. – Kit10

1

static_assert là chỉ thị của trình biên dịch. Nó cho phép bạn kiểm tra thông tin kiểu tại thời gian biên dịch. Nó sẽ gây ra một lỗi biên dịch và tạo ra một thông báo lỗi mà trong hầu hết các IDE bị bắt và hiển thị trong cửa sổ lỗi của IDE.

static_assert(sizeof(int) == 4,"int should be 4 bytes"); 

assert là để chạy, bạn có thể kiểm tra giá trị của biến. Nếu xác nhận không thành công thì xác nhận sẽ kích hoạt. Điều này sẽ gây ra một hộp thông báo lỗi sẽ xuất hiện trong thời gian chạy trong một số hệ điều hành (khẳng định thực hiện phụ thuộc)

assert(("mypointer should never be null!", mypointer != nullptr)); 
+1

Trình biên dịch "chỉ thị" có lẽ không hoàn toàn là thuật ngữ tôi muốn sử dụng ... –

+0

Macro khẳng định được xác định trong '' không lấy hai đối số – Joe

+0

@joe, phải, đã sửa cú pháp. –

11

static_assert có nghĩa là để làm cho biên soạn thất bại với thông điệp cụ thể, trong khi truyền thống assert là có nghĩa là để kết thúc thực hiện chương trình của bạn.

6

OK, tôi sẽ cắn:

  • Chỉ static_assert công trình nếu bạn muốn biên soạn để ngăn chặn không thành công nếu một điều kiện tĩnh bị vi phạm: static_assert(sizeof(void*) != 3, "Wrong machine word size"); * Chỉ khẳng định năng động có thể bắt điều kiện động: assert(argc == 1);

  • Các tuyên bố đơn giản if phải hợp lệ và có thể biên dịch được; xác nhận tĩnh gây ra lỗi biên dịch.

  • số

*) Một ví dụ thực tế có thể là để ngăn chặn việc lạm dụng mẫu công trình xây dựng chung chung, chẳng hạn như int x; std::move<int&&>(x).

3

Thực tiễn không tốt để sử dụng chúng?

Nếu bị lạm dụng, có, đặc biệt là assert.

Một sự lạm dụng tùy thuộc vào những tuyên bố assert đó để hoạt động. Bạn không bao giờ nên phụ thuộc vào assert để làm bất cứ điều gì vì mã có thể được biên dịch với NDEBUG được xác định và sau đó assert không làm gì cả. Mã sản xuất thường được biên dịch với NDEBUG được xác định để đảm bảo rằng các báo cáo assert đó biến mất.

Trừ khi bạn đang viết một chương trình một lần không hoạt động trong hơn một hoặc hai ngày, bạn không nên sử dụng để xác thực tính năng nhập của người dùng. Người dùng không quan tâm nơi mã không thành công và thư được in trông giống như một ngôn ngữ nước ngoài cho nhiều người dùng. Nó không cho người dùng biết cách sửa lỗi. Nó cũng rất không khoan nhượng, theo thiết kế. Thông báo được phát hành để phản hồi lỗi nhập của người dùng phải là thông báo cho người dùng biết cách khắc phục sự cố. Hành động tốt nhất sau thông báo là cung cấp cho người dùng một cách để sửa lỗi. Nếu điều đó không thể thực hiện được, và nếu đáp ứng khả thi duy nhất là kết thúc chương trình, chương trình sẽ chấm dứt sạch sẽ. Theo thiết kế, assert không dẫn đến tắt máy. Nó gọi số abort() thay vì exit().

Một hệ quả của abort() trên nhiều máy là tạo ra kết xuất lõi. Cốt lõi là một thông báo lỗi tuyệt vời cho một lập trình viên. Với một bãi chứa lõi, một lập trình viên có thể sử dụng trình gỡ rối để xem những gì đã xảy ra một cách chi tiết. Một nhược điểm của abort() là mọi thứ không được làm sạch. Hủy bỏ "chấm dứt chương trình mà không thực hiện các destructors cho các đối tượng của thời gian lưu trữ tự động hoặc tĩnh và không gọi các chức năng được chuyển đến atexit()."

Tóm lại: Không sao (và tốt) để sử dụng assert để kiểm tra lỗi lập trình, nhưng chỉ trong cài đặt phi sản xuất. Sử dụng một cái gì đó khác để kiểm tra lỗi người dùng.

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