Kiểu trả về của '?:' (Toán tử điều kiện ternary)


208

Tại sao đầu tiên trả về một tài liệu tham khảo?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

Trong khi thứ hai thì không?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

Trên thực tế, cái thứ hai hoàn toàn không biên dịch - "không phải giá trị trái của bài tập".


1
hmm, giống như tìm thấy một trường hợp đặc biệt để nướng bánh mì, đã không đến đây một lần
Ul thầm


Khi gán một kiểu cho biểu thức sẽ hàm ý ít nhất một thuật ngữ, thuật ngữ này sẽ không còn là giá trị l nữa.
Yves Daoust

Câu trả lời:


173

Biểu thức không có kiểu trả về, chúng có kiểu và - như được biết trong tiêu chuẩn C ++ mới nhất - một loại giá trị.

Một biểu thức điều kiện có thể là một giá trị trái hoặc một rvalue . Đây là thể loại giá trị của nó. (Đây là một phần của sự đơn giản hóa, trong C++11chúng ta có giá trị, xvalues ​​và prvalues.)

Trong điều kiện rất rộng và đơn giản, một giá trị trái đề cập đến một đối tượng trong bộ nhớ và một rvalue chỉ là một giá trị mà có thể không nhất thiết phải gắn liền với một đối tượng trong bộ nhớ.

Một biểu thức gán gán một giá trị cho một đối tượng để vật được gán phải là một giá trị .

Để một biểu thức có điều kiện ( ?:) là một giá trị (một lần nữa, theo nghĩa rộng và đơn giản), các toán hạng thứ hai và thứ ba phải là các giá trị cùng loại . Điều này là do loại và giá trị của biểu thức điều kiện được xác định tại thời điểm biên dịch và phải phù hợp cho dù điều kiện có đúng hay không. Nếu một trong các toán hạng phải được chuyển đổi sang loại khác để khớp với loại khác thì biểu thức điều kiện có thể là một giá trị vì kết quả của chuyển đổi này sẽ không phải là một giá trị .

Tài liệu tham khảo ISO / IEC 14882: 2011:

3.10 [basic.lval] Giá trị và giá trị (về các loại giá trị)

5.15 [expr.cond] Toán tử điều kiện (quy tắc cho loại biểu thức và loại giá trị mà biểu thức điều kiện có)

5.17 [expr.ass] Toán tử gán và gán ghép (yêu cầu các lhs của một phép gán phải là một giá trị có thể sửa đổi)


3
Và khi đọc lên trên Xvalue và prvalue (kể từ khi tôi đã không nghe nói về họ trước câu trả lời của bạn) Tôi đã xem qua bài SO ích này: stackoverflow.com/questions/3601602/...
mịn

an rvalue is just a value that may not necessarily be *attached* to an object in memory.Bạn có thể giải thích điều này trong thuật ngữ đơn giản hơn? . Ngoài ra, bạn có ý nghĩa type and value *category*gì? Cảm ơn
Mr.Anubis

@SoulReaper: prvalue, xvalue, glvaluelà các loại giá trị.
Xèo

@Xeo Tôi đánh giá cao sự giúp đỡ nhưng bạn có thể cho biết ý nghĩa của anh ấy bởi một giá trị chỉ là một giá trị có thể không nhất thiết phải được gắn vào một đối tượng trong bộ nhớ. ? với ví dụ?
Mr.Anubis

@SoulReaper: Tôi nghĩ anh ấy nói về những điều thích true, this, enumgiá trị. Những thứ đó là giá trị (giá trị "thuần túy"), nhưng không sống trong ký ức.
Xèo

57

Kiểu của ?:biểu thức ternary là kiểu phổ biến của đối số thứ hai và thứ ba của nó. Nếu cả hai loại đều giống nhau, bạn sẽ nhận được một tài liệu tham khảo. Nếu chúng có thể chuyển đổi lẫn nhau, một cái sẽ được chọn và cái kia được chuyển đổi (được thăng cấp trong trường hợp này). Vì bạn không thể trả lại tham chiếu giá trị cho tạm thời (biến được chuyển đổi / quảng cáo), loại của nó là loại giá trị.


nhưng y lớn hơn x, vì vậy không cần quảng cáo cho trường hợp cụ thể này, nó có thể trả về tham chiếu cho y. Hmm ... Nhưng tôi đồng ý, nó sẽ là lạ.
Yola

1
@ Mr.TAMER: Tôi muốn đào sâu hơn tiêu chuẩn. : <
Xeo

3
@Yola: Vì các loại là một khái niệm thời gian biên dịch trong C ++, nên giá trị trả về thực tế của biểu thức không thành vấn đề.
Xèo

1
Bạn không nhận được một tài liệu tham khảo trở lại, bạn nhận được giá trị.
Suma

1
@Xeo: Tuy nhiên, không phải theo thuật ngữ C ++;)
Sebastian Mach

19

Nó không thể trả về một giá trị vì nó sẽ phải hoàn toàn thúc đẩy loại xđể khớp với loại y(vì cả hai mặt :không cùng loại) và do đó nó phải tạo tạm thời.


Tiêu chuẩn nói gì? ( n1905 )

Biểu thức 5.17 Toán tử gán và gán ghép

5,17 / 3

Nếu toán hạng thứ hai và thứ ba có các loại khác nhau và có loại lớp (có thể đủ điều kiện cv), một nỗ lực được thực hiện để chuyển đổi từng toán hạng đó sang loại toán hạng khác. Quá trình xác định liệu một biểu thức toán hạng E1 có thể được chuyển đổi để phù hợp với biểu thức toán hạng E2 của loại T2 được xác định như sau:

- Nếu E2 là một giá trị: E1 có thể được chuyển đổi để khớp với E2 nếu E1 có thể được chuyển đổi hoàn toàn (mệnh đề 4) sang tham chiếu kiểu Kiểu thành T2, theo các ràng buộc mà trong chuyển đổi, tham chiếu phải liên kết trực tiếp (8.5.3 ) đến E1.

- Nếu E2 là một giá trị hoặc nếu chuyển đổi ở trên không thể được thực hiện:

- nếu E1 và E2 có loại lớp và các loại lớp bên dưới giống nhau hoặc một loại là lớp cơ sở của loại khác: E1 có thể được chuyển đổi để khớp với E2 nếu lớp của T2 cùng loại với hoặc lớp cơ sở của , lớp của T1 và chất lượng cv của T2 là cùng loại cv, hoặc bằng cấp cv lớn hơn so với chất lượng cv của T1. Nếu chuyển đổi được áp dụng, E1 được thay đổi thành giá trị loại T2 vẫn tham chiếu đến đối tượng lớp nguồn ban đầu (hoặc tiểu dự án thích hợp của chúng). [ Lưu ý: đó là, không có bản sao được thực hiện. - lưu ý cuối ] bằng cách sao chép khởi tạo tạm thời loại T2 từ E1 và sử dụng tạm thời đó làm toán hạng đã chuyển đổi.

Mặt khác (ví dụ, nếu E1hoặc E2 có loại không phải là lớp hoặc nếu cả hai đều có loại lớp nhưng các lớp bên dưới không giống nhau hoặc một lớp cơ sở của loại khác): E1 có thể được chuyển đổi để khớp với E2 nếu có thể là E1 hoàn toàn chuyển đổi thành loại mà biểu thức E2 sẽ có nếu E2 được chuyển đổi thành giá trị (hoặc loại có, nếu E2 là giá trị).

Sử dụng quy trình này, nó được xác định liệu toán hạng thứ hai có thể được chuyển đổi để phù hợp với toán hạng thứ ba hay không và liệu toán hạng thứ ba có thể được chuyển đổi để phù hợp với toán hạng thứ hai hay không. Nếu cả hai có thể được chuyển đổi, hoặc một có thể được chuyển đổi nhưng chuyển đổi không rõ ràng, chương trình không được định dạng. Nếu không thể chuyển đổi, các toán hạng được giữ nguyên và kiểm tra thêm được thực hiện như mô tả dưới đây. Nếu chính xác một chuyển đổi là có thể, chuyển đổi đó được áp dụng cho toán hạng đã chọn và toán hạng được chuyển đổi được sử dụng thay cho toán hạng gốc cho phần còn lại của phần này.


5,17 / 4

Nếu toán hạng thứ hai và thứ ba là giá trị và có cùng loại, kết quả là loại đó và là giá trị và nó là trường bit nếu toán hạng thứ hai hoặc thứ ba là trường bit hoặc nếu cả hai đều là bit- lĩnh vực.


5,17 / 5

Mặt khác, kết quả là một giá trị. Nếu các toán hạng thứ hai và thứ ba không có cùng loại và có loại lớp (có thể đủ điều kiện cv), độ phân giải quá tải được sử dụng để xác định các chuyển đổi (nếu có) được áp dụng cho toán hạng (13.3.1.2, 13.6) . Nếu độ phân giải quá tải không thành công, chương trình không được định dạng. Mặt khác, các chuyển đổi được xác định như vậy được áp dụng và các toán hạng được chuyển đổi được sử dụng thay cho các toán hạng ban đầu cho phần còn lại của phần này.

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.