19

Gần đây tôi đã chạy băng qua tình huống sau đây:để đánh giá các đối số chức năng và đối số mặc định

#include <iostream> 

int *p = 0; 

int f() { 
    p = new int(10); 
    return 0; 
} 

void g(int x, int *y = p) { 
    std::cout << y << std::endl; 
} 

int main() { 
    g(f()); 
} 

này khá tinh tế, vì bạn thường không mong đợi các đối số mặc định để thay đổi trong đánh giá của họ đối với cuộc gọi chức năng . Tôi đã phải nhìn vào hội đồng để phát hiện lỗi này.

Bây giờ câu hỏi của tôi là: Hành vi này có thực sự không xác định, vì không có bất kỳ đảm bảo nào liên quan đến thứ tự đánh giá các đối số hàm?

Trả lời

15

Thứ tự đánh giá (tức là xác định giá trị) của đối số hàm không được chỉ định. Trình biên dịch là miễn phí để thực hiện chúng theo thứ tự bất kỳ, và thậm chí xen kẽ nếu không có yếu tố khác ngăn chặn nó làm như vậy.

Đánh giá các đối số mặc định xảy ra trong ngữ cảnh của người gọi, không phải là callee. Vì vậy, các cuộc gọi đến f() là cần thiết cho một đối số, và đọc biến toàn cầu p cho khác. Thứ tự này xảy ra trong không được chỉ định, vì vậy toàn cầu có thể được đọc trước hoặc sau cuộc gọi đến f().

+0

"Đánh giá các đối số mặc định xảy ra trong ngữ cảnh của người gọi" Bạn có tham chiếu trong tiêu chuẩn C++ hiện tại cho xác nhận quyền sở hữu này không? – phlipsy

+1

Có một lưu ý không quy định trong 1.9p11 nói rõ ràng. Ngoài ra, tôi nghĩ nó chỉ được ngụ ý bởi sự thiếu phân biệt với các lập luận khác. –

+2

@phlipsy xem [dcl.fct.default]/9 "Đối số mặc định được đánh giá mỗi khi hàm được gọi. Thứ tự đánh giá hàm số không xác định.", Tôi nghĩ điều này ngụ ý rõ ràng rằng 'g (f()) 'giống như' g (f(), p) ' –

13

Nếu tôi hiểu nó một cách chính xác, cuộc gọi của bạn

g(f()); 

tương đương với

g(f(), p); 

do việc kê khai

void g(int x, int *y = p); 

Và đối số cho các g chức năng, f()p , có thể được đánh giá theo bất kỳ thứ tự nào, vì vậy bạn có thể nhận được g được gọi là y được gán cho số không (nếu p được đánh giá trước, sau đó trả về giá trị ban đầu) hoặc con trỏ mảng mới được phân bổ (nếu f() được đánh giá đầu tiên và gán giá trị mới cho p làm hiệu ứng phụ).

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