2009-08-18 54 views
5

Điều tôi thực sự muốn là toán tử || =.hành vi của bool với toán tử phi boolean

old_value = old_value || possible_new_value; 
old_value ||= possible_new_value; 

Dòng thứ hai là lỗi trình biên dịch (C++ không có toán tử || =).

Vì vậy, các tùy chọn khác của tôi là gì?

old_value += possible_new_value; 
old_value |= possible_new_value; 

Khi tôi đang ở chủ đề Bool hoạt động như thế nào với các toán tử khác không phải là boolean?

- 
-= 
& 
&= 
... 

Tôi có thể xác minh những điều này theo kinh nghiệm, nhưng tôi quan tâm nhất đến những gì tiêu chuẩn nói.

Trả lời

12

Theo 4.7 (chuyển đổi Integral), khoản 4, "Nếu loại đích là bool, xem 4.12.Nếu loại nguồn là bool, giá trị false được chuyển thành 0 và giá trị true được chuyển thành giá trị. "Trong 4.12," Giá trị số học, số đếm, con trỏ hoặc con trỏ thành loại thành viên có thể được chuyển đổi thành giá trị loại bool. Giá trị bằng không, giá trị con trỏ null hoặc giá trị con trỏ thành viên null được chuyển đổi thành false; bất kỳ giá trị khác được chuyển thành true."

Trong một bối cảnh nơi bool toán hạng không được phép nhưng toán hạng không thể thiếu được, các bool sẽ được chuyển đổi sang một loại không thể thiếu. Khi kết quả số nguyên được lưu trữ trong một biến bool, nó sẽ được chuyển đổi thành bool.

Do đó, bạn sẽ có thể sử dụng dấu + và * làm boolean hoặc và, và bạn cũng có thể sử dụng | và &.) & bool3 sẽ mang lại false nếu cả ba biến là true. ((1 + 1) & 1 là 2 & 1, là 0 hoặc sai.)

Hãy nhớ rằng | và || không làm việc giống hệt ngay cả ở đây. | sẽ đánh giá cả hai mặt, và sau đó đánh giá bitwise hoặc. || sẽ đánh giá toán hạng đầu tiên, sau đó chỉ khi đó là sai sẽ đánh giá thứ hai.

Tôi sẽ không thảo luận các vấn đề về phong cách ở đây, nhưng nếu tôi làm bất cứ điều gì như thế, tôi chắc chắn sẽ nhận xét nó để mọi người biết tôi đang làm gì và tại sao.

+0

tuyệt vời, cảm ơn. Tôi sẽ bỏ phiếu hai lần nếu tôi có thể –

+0

+1 để trích dẫn tiêu chuẩn (và trả lời câu hỏi), đồng thời thêm nhận xét về phong cách – Gabe

0

Không sử dụng |=&= với bools. Họ có thể làm việc hầu hết thời gian, nhưng nó vẫn còn sai. Thông thường, loại bool chỉ là một int hoặc char glorified. Trong mã cũ hơn mà tôi đã làm việc với, BOOL chỉ là typedef'd để int hoặc char. Trong những trường hợp này, bạn có thể nhận được câu trả lời sai nếu bằng cách nào đó các bit đã được thao tác (Ví dụ, 1&2 là 0 (sai)). Và tôi không chắc chắn, nhưng tôi nghĩ rằng kết quả của các toán tử bitwise sẽ là một int, ngay cả đối với bools.

+0

suy nghĩ về + =? –

+3

Nếu cả hai biến được khai báo là ''bool'', trong hoàn cảnh nào (ngoài trình biên dịch bị hỏng - hoặc trình biên dịch chuẩn không chuẩn, hay còn gọi là trình biên dịch chuẩn) thì chúng có sai không? –

+0

nếu bất cứ điều gì bao giờ được thông qua như một void * hoặc một cái gì đó, và bạn có một API bằng cách sử dụng loại như một int, bạn không thể được đảm bảo rằng họ luôn luôn sẽ sử dụng "1" cho sự thật, như trái ngược với bất kỳ khác không số nguyên -zero. – Kip

0
if (!old_value) 
    old_value = possible_new_value; 

Điều này tương đương với điều kiện gốc. Nó có thể tạo ra mã đơn giản hơn vì nó sẽ không luôn luôn gán cho old_value - nhưng tôi sẽ không mong đợi sự khác biệt hiệu suất để có thể dễ dàng đo lường được trong một chương trình lớn.

0

Một điểm khác biệt là các toán tử logic như || đảm bảo thứ tự đánh giá và cung cấp đoản mạch, trong đó các toán tử bit và số học không.

Tôi tin rằng trình biên dịch sẽ xử lý toán tử phi logic bằng cách chuyển đổi các giá trị số sang số (0, 1) áp dụng toán tử và chuyển đổi ngược lại. Các chuyển đổi này được xác định nghiêm ngặt theo tiêu chuẩn, ví dụ:

Giá trị của số học, đếm, con trỏ hoặc loại thành viên có thể được chuyển đổi thành giá trị boolue loại bool. Một giá trị bằng không, giá trị con trỏ null, hoặc giá trị con trỏ thành viên null được chuyển thành false bất kỳ giá trị nào khác được chuyển thành true.

1

Bạn có thể sử dụng toán tử bậc ba không?

old_value = !old_value ? possible_new_value : old_value;

+0

tại sao điều đó sẽ thích hợp hơn với 'old_value = old_value || ngắn hơn new_value; '? – Kip

+1

Dường như tôi đã đọc sai câu hỏi :) Không có lý do gì để làm điều đó thay vì 'old_value = old_value || new_value; ', đặc biệt là vì cái sau có thể đọc được nhiều hơn. – Cinder6

0

Nasty hackery vĩ mô:

#define UPDATE(x) x = x 

UPDATE(old_value) || possible_new_value; 

Nhưng tôi không khuyên bạn nên điều này cả. Các macro như thế này là một ý tưởng rất tồi vì nhiều lý do.

Một chức năng lành mạnh hơn, nhưng nếu không có sự ngắn mạch:

bool set_or(bool &old, bool value) { 
    return (old = old || value); 
} 

... 

bool v = false; 
set_or(v, true); 
+0

Tất nhiên, điều này chỉ hoạt động khi x là một biến, và chỉ thất bại rõ ràng khi x không gió lên với một lvalue, và phụ thuộc chủ yếu vào việc xây dựng một biểu thức một nửa và một nửa của vĩ mô. Ewwwww. –

+0

Macro này sẽ thất bại nếu đánh giá 'possible_new_value' có tác dụng phụ. –

+0

Nếu nó không phụ thuộc vào ngữ nghĩa của '|| =' nên là gì. Tôi không thực sự chắc chắn nếu ngắn mạch sẽ được dự định có hay không. – sth

4

Các sayeth tiêu chuẩn:

4.5-4 "Khuyến mãi Integral"

Một rvalue kiểu bool có thể được chuyển đổi thành một rvalue kiểu int, với sai trở thành zero và đúng sự thật trở thành một.

5.17-7 "Chuyển nhượng nhà khai thác"

Hành vi của một biểu hiện của sự hình thức E1 op = E2 tương đương với E1 = E1 E2 op trừ E1 được đánh giá chỉ Một lần. Trong + = và - =, E1 sẽ là hoặc có loại số học hoặc là con trỏ đến một loại đối tượng có thể được xác định hoàn toàn hoàn toàn được xác định. Trong tất cả các trường hợp khác, E1 phải có số học .

4.12-1 "Boolean Chuyển đổi"

Một rvalue của số học, điều tra, con trỏ, hoặc con trỏ đến loại thành viên có thể được chuyển đổi sang một rvalue loại bool. Giá trị bằng không, giá trị con trỏ rỗng giá trị hoặc giá trị con trỏ thành viên null là được chuyển thành false; bất kỳ giá trị nào khác là được chuyển thành true.

Vì vậy, điều này có nghĩa rằng

b1 += b2 

đâu b1 và b2 là boolean sẽ tương đương với

b1 = b1 + b2 

Và b1 và b2 sẽ được thăng 0/1 số nguyên, và sau đó chuyển đổi trở lại boolean trên quy tắc rằng bất cứ điều gì khác hơn 0 là đúng sự thật.

Vì vậy, các bảng thật là

 
      true false 
true  true true 
false true false 

nên + = làm trong công việc thực tế như || = theo tiêu chuẩn. Tuy nhiên, điều này có thể sẽ gây nhầm lẫn cho các lập trình viên khác, vì vậy tôi sẽ tránh nó vẫn còn.

+0

Bao gồm tuyệt đối 5.17-7. –

+0

+1 để trích dẫn tiêu chuẩn và cho bảng phân tích rõ ràng của + = và lời khuyên tránh + =. –

0

Tôi tin rằng tiêu chuẩn xác định rõ ràng đúng và sai là 1 và 0, vì vậy bạn có thể sử dụng các toán tử bitwise một cách an toàn trên các giá trị bool. Các loại khác có thể được xử lý ngầm như bools trong ngữ cảnh khác cần được chuyển đổi rõ ràng để làm việc này một cách đáng tin cậy.

Tôi đã thấy trình biên dịch của Microsoft tạo ra cảnh báo xấu mỗi khi bạn làm điều này, bởi vì nó cho rằng có nguy cơ trong việc chuyển đổi ngầm kết quả int thành bool.

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