2011-07-14 7 views
8

Tôi nghi ngờ chuỗi các hàm sau sẽ dẫn đến chuỗi không xác định theo tiêu chuẩn C++ (giả sử C++ 0x). Chỉ muốn có một xác nhận và nếu bất cứ ai có thể cung cấp một lời giải thích, tôi sẽ đánh giá cao nó.Mã này có được xác định rõ không?

#include <iostream> 

struct TFoo 
{ 
    TFoo(int) 
    { 
     std::cout<<"TFoo"<<std::endl; 
    }; 
    TFoo foobar1(int) 
    { 
     std::cout<<"foobar1"<<std::endl; 
     return *this; 
    }; 
    TFoo foobar2(int) 
    { 
     std::cout<<"foobar2"<<std::endl; 
     return *this; 
    }; 
    static int bar1() 
    { 
     std::cout<<"bar1"<<std::endl; 
     return 0; 
    }; 
    static int bar2() 
    { 
     std::cout<<"bar2"<<std::endl; 
     return 0; 
    }; 
    static int bar3() 
    { 
     std::cout<<"bar3"<<std::endl; 
     return 0; 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    // is the sequence well defined for bar1, bar2 and bar3? 
    TFoo(TFoo::bar1()).foobar1(TFoo::bar2()).foobar2(TFoo::bar3()); 
} 

* chỉnh sửa: bị gỡ bỏ __fastcall specifier cho các chức năng (không cần thiết/liên quan đến câu hỏi).

+1

Tôi không có nghĩa là để đi qua như nitpicky, nhưng về mặt kỹ thuật nói '__fastcall' không phải là một phần của spec C++, vì vậy tôi không nghĩ rằng spec có bất cứ điều gì để nói về điều này. Có lý do gì bạn đưa vào đây không? Hay là câu hỏi cụ thể về sự tương tác của '__fastcall' với các điểm chuỗi? – templatetypedef

Trả lời

8

Thứ tự đánh giá không được chỉ định. Các phần có liên quan của dự thảo C++0x spec là 1,9, đoạn 14 và 15:

14 Mỗi giá trị tính toán và phụ ảnh hưởng kết hợp với một toàn biểu được lập trình tự trước mỗi giá trị tính toán và phụ ảnh hưởng liên quan đến việc tiếp theo biểu thức đầy đủ để được đánh giá.

15 Trừ khi được ghi chú, việc đánh giá toán hạng của các toán tử riêng lẻ và các biểu thức con của các biểu thức riêng lẻ không được kết thúc.

Ở đây có liên quan toàn biểu là:

TFoo(TFoo::bar1()).foobar1(TFoo::bar2()).foobar2(TFoo::bar3()); 

Và vì vậy việc đánh giá subexpressions của nó là unsequenced (trừ khi có một ngoại lệ ghi nhận ở đâu đó mà tôi bị mất).

Tôi khá chắc chắn các tiêu chuẩn trước đó bao gồm ngôn ngữ có cùng tác dụng nhưng về "điểm chuỗi".

[sửa]

Đoạn 15 cũng nói:

Khi gọi một hàm (có hoặc không có chức năng là inline), mỗi giá trị tính toán và phụ ảnh hưởng kết hợp với bất kỳ biểu hiện lý luận, hoặc với biểu thức postfix chỉ định hàm được gọi, được sắp xếp theo trình tự trước khi thực hiện mọi biểu thức hoặc câu lệnh trong phần thân của hàm được gọi. [Lưu ý: Các tính toán giá trị và các hiệu ứng phụ liên quan đến các biểu thức đối số khác nhau không được kết nối.- lưu ý cuối cùng]

"Biểu thức postfix chỉ định hàm được gọi" giống như foo().bar trong foo().bar().

"Lưu ý" ở đây chỉ làm rõ rằng thứ tự đánh giá đối số là không phải là ngoại lệ đối với "thứ tự không xác định" mặc định. Theo suy luận, không phải là thứ tự đánh giá được kết hợp với "biểu thức postfix chỉ định hàm được gọi"; hoặc nếu bạn thích, thứ tự đánh giá của biểu thức cho đối số this. (Nếu có một ngoại lệ, đây sẽ là nơi tự nhiên để xác định nó. Hoặc có thể phần 5.2.2 nói về các cuộc gọi chức năng. Không có phần nào nói về thứ tự đánh giá cho ví dụ này, vì vậy nó không được chỉ định.)

+0

'Trừ khi ghi chú' - điều này để lại một chút suy nghĩ ... –

+0

@Zach: Thật vậy. Nhưng nếu bạn dự định phụ thuộc vào thứ tự đánh giá, bạn cần phải tìm một quy tắc cụ thể để đặt thứ tự. C/C++ đã luôn luôn được lỏng lẻo về việc xác định điều này để cung cấp cho trình biên dịch và CPU phòng để sắp xếp lại thứ cho hiệu suất. – Nemo

+1

IMO cần lưu ý là 'foobar1' được gọi trước' foobar2'. Vì vậy, thứ tự bị ràng buộc (vì kết quả của 'foobar1()' cần phải được đánh giá trước khi nó được sử dụng như một toán hạng của toán tử '', 1.9p15), mặc dù hầu như không được chỉ định đối với các cuộc gọi khác. –

1

Có, thứ tự đánh giá đối số chức năng không được chỉ định.

Đối với tôi, 4.5.2 gcc trên linux sản xuất

bar3 
bar2 
bar1 
TFoo 
foobar1 
foobar2 

nhưng kêu vang ++ trên Linux và gcc 3.4.6 trên solaris sản xuất

bar1 
TFoo 
bar2 
foobar1 
bar3 
foobar2 

Để phân tích một ví dụ đơn giản, TFoo(0).foobar1(TFoo::bar2()); là lời kêu gọi đến TFoo::foobar1 có hai đối số: kết quả của biểu thức con TFoo(0) (làm đối số ẩn this) và kết quả của biểu thức con Tfoo::bar2(). Đối với tôi, gcc thực thi bar2() trước tiên, sau đó là hàm tạo của TFoo và sau đó gọi foobar1(), trong khi ví dụ clang ++, thực thi hàm tạo của TFoo trước, sau đó bar2() và sau đó gọi foobar1().

+0

Tôi biết thứ tự đánh giá các đối số hàm không xác định nhưng trong trường hợp này, nó thực sự là thứ tự của eval đối số hàm (số ít) cho mỗi hàm xích (có thứ tự xác định) đang được đề cập. Bất kỳ tiêu chuẩn có liên quan nào để nói điều này thực sự không được chỉ định? –

+0

@Zach Saw: Các hàm thành viên cũng lấy 'this' làm đối số ngụ ý. – Cubbi

+0

chăm sóc để xây dựng? điều đó có nghĩa là thứ tự không được chỉ định quá cho các hàm xích (foobar1 và foobar2)? –