2016-05-19 74 views
57

Đối với một đối số mặc định trong C++, giá trị cần phải là một hằng số hoặc một đối số khác sẽ làm gì?Đối số mặc định của C++ có thể được khởi tạo với đối số khác không?

Tức là, công việc sau đây có thể không?

RateLimiter(unsigned double rateInPermitsPerSecond, 
      unsigned int maxAccumulatedPermits = rateInPermitsPerSecond); 

Hiện nay tôi đang nhận được một lỗi:

RateLimiter.h:13: error: ‘rateInPermitsPerSecond’ was not declared in this scope

+4

@BaummitAugen khá kết luận phải không? –

+0

@RichardHodges Yep, trình biên dịch đã đúng về số tiền ở đây. –

+1

Tôi đang tìm kiếm một lời giải thích hợp lý vì sao nó không được phép. – user1918858

Trả lời

78

lập luận khác không thể được sử dụng như là giá trị mặc định. Các trạng thái tiêu chuẩn:

8.3.6 Default arguments
...
9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in a default argument, even if they are not evaluated.

và minh họa nó với các mẫu sau:

int f(int a, int b = a); // error: parameter a 
         // used as default argument 
70

Không, đó không thể làm việc vì việc đánh giá các đối số chức năng không giải trình tự. Nó cũng không hoạt động vì tiêu chuẩn không cho phép nó, nhưng tôi đoán điều đó là hiển nhiên.

Sử dụng một quá tải thay vì:

void fun(int, int) {} 

void fun(int i) { 
    fun(i, i); 
} 
36

I was looking for an logical explanation for why it is not allowed

Đây thực sự là một câu hỏi hay. Lý do là C++ không ủy nhiệm thứ tự đánh giá các đối số.

Vì vậy, hãy tưởng tượng một kịch bản hơi phức tạp hơn:

int f(int a, int b = ++a); 

... followed by ... 

int a = 1; 
f(a); 

C++ không uỷ quyền cho tự đánh giá của các đối số, nhớ không?

Vậy giá trị của b là bao nhiêu?

f(a) có thể đánh giá cho một trong hai:

f(1, 2), hoặc f(2, 2), tùy thuộc vào trình tự đánh giá của các đối số.

Do đó, hành vi sẽ không xác định (và thậm chí không thể xác định).

Hơn nữa, hãy xem xét điều gì có thể xảy ra khi a và b là các đối tượng phức tạp mà các nhà xây dựng và nhà khai thác bản sao có tác dụng phụ.

Thứ tự của những tác dụng phụ đó sẽ không được xác định.

+1

ví dụ hay ... những gì về int f (int a = b + +, int b = a ++); Tôi cần điều đó cho một vòng lặp ưa thích chết – Mzn

+4

@ MHZ hành vi không xác định nếu nó là hợp pháp, mà nó không phải là. –

11

Bạn không thể làm những việc như vậy vì tiêu chuẩn không cho phép. Tuy nhiên kể từ khi đối số mặc định một cách hiệu quả chỉ xác định quá tải chức năng mới, bạn có thể nhận được hiệu quả mong muốn bằng cách định nghĩa một cách rõ ràng một tình trạng quá tải như:

void RateLimiter(unsigned int rateInPermitsPerSecond, 
       unsigned int maxAccumulatedPermits); 

inline void RateLimiter(unsigned int rateInPermitsPerSecond) 
{ return RateLimiter(rateInPermitsPerSecond,rateInPermitsPerSecond); } 

Điều này cho thấy tiêu chuẩn cấm này là nửa vời, theo đề nghị của ngôn ngữ (" Do đó ... sẽ không ... "). Họ không muốn trải qua những rắc rối khi thực hiện điều này với hiệu ứng tương tự như những gì khai báo quá tải rõ ràng sẽ làm: nếu muốn, họ có thể đã xác định rằng các đối số mặc định được đánh giá sau các đối số được cung cấp rõ ràng và từ trái sang phải .Điều này sẽ không có bất kỳ ảnh hưởng nào đến quy tắc rằng thứ tự đánh giá các biểu thức đối số trong một cuộc gọi hàm không được chỉ định (vì các đối số mặc định không tương ứng với các biểu thức như vậy, chúng hoàn toàn tách biệt và thậm chí không nằm trong cùng phạm vi từ vựng). Mặt khác nếu (như họ đã làm) họ thích không cho phép điều này, họ có thể chỉ nói "sẽ không" mà không cần phải biện minh cho mình từ một số quy tắc khác (nhưng có thể với chú thích giải thích).

2

For a default argument in C++, does the value need to be a constant or will another argument do?

Giá trị mặc định của đối số không thể là đối số khác. Tuy nhiên, điều đó không có nghĩa là nó phải là một hằng số. Nó có thể là giá trị trả về của một cuộc gọi hàm.

int getNextDefaultID() 
{ 
    static int id = 0; 
    return ++id; 
} 

struct Foo 
{ 
    Foo(int data, int id = getNextDefaultID()) : data_(data), id_(id) {} 
    int data_; 
    int id_; 
}; 

int main() 
{ 
    Foo f1(10);  // Gets the next default ID. 
    Foo f2(20, 999); // ID is specified. 
} 
Các vấn đề liên quan