2013-02-11 37 views
8

Tôi gặp khó khăn trong việc hiểu chuỗi các cuộc gọi trong mã bên dưới. Tôi đã chờ đợi để xem kết quả dưới đâythứ tự thực hiện trong toán tử <<

A1B2 

Trong khi tôi có thể thấy rằng đầu ra tôi nhận được là

BA12 

Tôi nghĩ rằng cuộc gọi std::cout<< b->fooA() << b->fooB() << std::endl tương đương với gọi

std::cout.operator<<(b->fooA()).operator<< (b->fooB()) 

nhưng tôi có thể thấy rằng đây không phải là trường hợp. Bạn có thể giúp tôi hiểu rõ hơn về cách thức hoạt động của nó và mối quan hệ với toàn cầu operator<<? Đây có phải là lần cuối cùng được gọi trong chuỗi này không?

Trân

AFAG

#include <iostream> 

    struct cbase{ 
     int fooA(){ 
      std::cout<<"A"; 
      return 1; 
     } 
     int fooB(){ 
      std::cout <<"B"; 
      return 2; 
     } 
    }; 

    void printcbase(cbase* b){ 
     std::cout << b->fooA() << b->fooB() << std::endl; 
    } 

    int main(){ 
     cbase b; 
     printcbase(&b); 
    } 
+3

Bạn đúng khi nghĩ rằng nó tương đương với điều đó. Tuy nhiên, bạn đang đưa ra giả thiết sai lầm rằng có một thứ tự đánh giá được xác định rõ ràng. Không có.Đó là tất cả. –

+0

Thứ tự đánh giá subexpression không được đảm bảo ở đây (và nó * có * là một bản sao, nhưng tôi không thể tìm thấy một câu hỏi kinh điển tốt ngay bây giờ) –

+0

'AB12' hoặc' BA12' là kết quả đầu ra có thể. 'A1B2' không phải là (hy vọng). – jrok

Trả lời

8

Trình biên dịch có thể đánh giá chức năng printcbase() như thế này:

void printcbase(cbase* b){ 
    int a = b->FooA(); // line 1 
    int b = b->FooB(); // line 2 
    std::cout << a;  // line 3 
    std::cout << b;  // line 4 
    stc::cout << std::endl; 
} 

hoặc một số nhiều permutatins dòng đánh dấu là 1 - 4. Bạn chỉ đảm bảo rằng dòng 1 được thực hiện trước dòng 3 và dòng 2 trước dòng 4 (và tất nhiên dòng 3 trước dòng 4). Tiêu chuẩn không nói nhiều hơn và thực sự bạn có thể mong đợi các kết quả khác nhau với các trình biên dịch C++ khác nhau.

+0

một ràng buộc bị thiếu dòng 3 trước dòng 4. –

+0

Vâng, đúng như vậy hiển nhiên, đó không phải là một điểm suy nghĩ của tôi. Tôi sẽ thêm nó. Cảm ơn. – mity

4

Thứ tự thực hiện << được xác định rõ nhưng thứ tự đánh giá biểu thức con không được xác định trong C++. This article and the C code example minh họa sự cố bạn đã đề cập.

BA12AB12 đều chính xác. Trong đoạn mã sau:

std::cout<< b->fooA() << b->fooB() 

1 sẽ xuất hiện trước 2 nhưng A có thể xuất hiện trước hoặc sau B kể từ khi biên dịch không hứa hẹn cho dù đó sẽ đánh giá fooA hoặc fooB đầu tiên.

1

Toán tử thay đổi là liên kết trái; a << b << c được đọc là (a << b) << c, có nghĩa là nếu a là loại có thành viên do người dùng xác định operator<< (và trả về loại đó) thì biểu thức sẽ là a.operator<<(b).operator<<(c). Nếu thay vào đó, miễn phí operator<< được sử dụng, thì điều này sẽ được đọc là operator<<(operator<<(a, b), c).

Vì vậy, việc đánh giá a << b được giải mã trước khi đánh giá của (a << b) << c, nhưng không có sự phụ thuộc trình tự giữa việc đánh giá bc:

a << b << c[1] 
|   | 
a << b[2] | 
| | c[5] 
a[3] b[4] 

Nếu chúng ta đánh số các tác dụng phụ như trên, thì tác dụng phụ có thể được sắp xếp theo trình tự như sau:

54321 
53421 
45321 
43521 
43251 
35421 
34521 
34251 
Các vấn đề liên quan