2012-03-06 48 views
5

ví dụ chức năng này f được định nghĩa như thế này:Tại sao bạn có thể trả về hàm bằng cách tham chiếu cho biến cục bộ chứ không phải cho biến tạm thời? C++

int f(int x){return x;} 

như bạn đã biết Bạn không thể gán một tham chiếu đến tạm int này:

int& rf=f(2);// this will give an error 

nhưng nếu tôi xác định lại chức năng của tôi f như thế này :

int& f(int x){return x;} 
f(2);// so now f(2) is a reference of x, which has been destroyed 

vì vậy câu hỏi của tôi là: làm thế nào trình biên dịch không cho phép bạn tạo tham chiếu đến tạm thời orary mà sẽ bị phá hủy sau khi statment (int the 1st case). và mặt khác nó cho phép bạn tạo một tham chiếu f (2) tới x trong khi trình biên dịch biết rằng cái này sẽ bị hủy sau return.

+1

Đây là UB (tốt, truy cập tham chiếu, dù sao) và bất kỳ trình biên dịch lành mạnh nào cũng cảnh báo bạn về nó. –

Trả lời

7

Trả về một tham chiếu đến một địa phương là cái gì đó có thể khó khăn hoặc không thể cho trình biên dịch để phát hiện. Ví dụ:

int & f() 
{ 
    int x; 
    extern int & g(int & x); 

    // Does this return a reference to "x"? 
    // The compiler has no way to tell. 
    return g(x); 
} 

Ngay cả khi không gọi hàm bên ngoài, vẫn khó phân tích luồng chương trình phức tạp để biết tham chiếu trả về có phải là cục bộ hay không; thay vì cố gắng xác định những gì được tính là "đủ đơn giản" để chẩn đoán, tiêu chuẩn không yêu cầu chẩn đoán - nó chỉ nói rằng nó mang lại hành vi không xác định. Một trình biên dịch tốt nên đưa ra một cảnh báo, ít nhất là trong các trường hợp đơn giản.

Ràng buộc một tham chiếu tạm thời không phải là một cái gì đó mà trình biên dịch có thể dễ dàng phát hiện và do đó tiêu chuẩn yêu cầu chẩn đoán cho điều đó.

1

Bởi vì, theo quy định của tiêu chuẩn, trả về tham chiếu đến một biến tạm thời từ một hàm là hành vi không xác định.

Có chuyện gì thực sự là định nghĩa hàm:

int& f(int x) 
{ 
    return x; 
} 
0

nó không phải là một ý tưởng tốt để trở về bằng cách tham chiếu trừ khi bạn chắc chắn tham chiếu bạn đang trở về vẫn sẽ được chỉ vào một cái gì đó có giá trị.

nếu không, hành vi không xác định được mong đợi.

vì biến là địa phương, bạn có thể chắc chắn rằng teh tham chiếu là không hợp lệ

+2

Vì biến là địa phương, bạn có thể chắc chắn nó không hợp lệ. –

1

Bạn có thể ràng buộc giá trị tạm thời thành tham chiếu const để kéo dài tuổi thọ của nó.

const int& rf=f(2); 
0

Vấn đề là ngữ nghĩa không có sự khác biệt giữa một biến trên một chồng, hoặc một biến trên heap vv - Vì vậy, các ngôn ngữ không có lựa chọn nào khác cho phép điều này, ngay cả khi đó là hành vi không xác định. Trong ví dụ đầu tiên bạn nhận được một lỗi biên dịch dễ dàng, bởi vì bạn đang cố gắng ràng buộc một tham chiếu trên một biến tạm thời, có thể bị cấm bởi ngôn ngữ.

+0

vâng tôi hiểu điều đó nhưng tại sao nó lại làm việc cho ví dụ thứ hai? và lý do tại sao bạn đề cập đến heap, và tôi đã không nói bất cứ điều gì về heap – AlexDan

+0

@AbdessamadBond Có câu trả lời tại sao ví dụ thứ hai của bạn không hoạt động .. và tôi đã đề cập đến đống, bởi vì trả về một tham chiếu đến một biến trên heap ok (ngay cả khi nó có lẽ là phong cách xấu). Về mặt ngữ nghĩa không có sự khác biệt giữa một biến trên heap và một trên stack, trong khi có một sự khác biệt giữa một biến và một giá trị tạm thời. – cooky451

1

Để từ chối đoạn mã đầu tiên của bạn, trình biên dịch áp dụng quy tắc đơn giản mà bạn không thể trực tiếp ràng buộc tạm thời với tham chiếu không phải const.

Để loại bỏ thứ hai, trình biên dịch có thể áp dụng quy tắc return của hàm trả về tham chiếu không được là tên của biến tự động (bao gồm tham số hàm giá trị). Điều đó dường như với tôi một quy tắc khá dễ dàng.

Tôi không biết tại sao tiêu chuẩn không chỉ định rằng làm như vậy là không đúng định dạng. Tôi không thể nghĩ ra bất kỳ việc sử dụng hợp lệ nào cho nó, nhưng có lẽ tại thời điểm chuẩn đầu tiên nó sẽ tạo ra một gánh nặng quá mức đối với một số việc thực hiện hoặc khác. Hoặc có lẽ nó đã cảm thấy rằng nó chỉ là một nửa sửa chữa và không đáng làm phiền với (có rất nhiều cách khác để tạo ra một tham chiếu lơ lửng, điều này chỉ chặn một trong số họ).

Lý do tại sao tiêu chuẩn không nói chung dừng bạn tạo một tham chiếu không const ràng buộc với một tạm thời là có những lúc OK. Ví dụ:

struct Foo { 
    static void set(Foo &f) { f.val = 0; } 
    int val; 
    int bar() { 
     set(*this); 
     return val; 
    } 
}; 

std::cout << Foo().bar() << "\n"; 

Đây Foo() là tạm thời, và dòng set(*this) liên kết nó vào một tài liệu tham khảo không const (nhưng không trực tiếp, nó sử dụng một biểu thức vế trái *this đó đề cập đến một tạm thời một số lần nhưng không phải người khác) . Không có vấn đề ở đây, các tài liệu tham khảo tạm thời outlives. Vì vậy, nó sẽ là không cần thiết hạn chế đối với ngôn ngữ bằng cách nào đó ngăn chặn bất kỳ tạm thời từ bao giờ bị ràng buộc với bất kỳ tham chiếu không const.

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