2011-08-12 41 views
6

tôi chỉ xây dựng một trong những dự án của chúng tôi tại nơi làm việc và tôi thấy một chức năng mới được bổ sung:Cảnh báo C4172: Trả lại tham chiếu đến const std :: chuỗi được liên kết với biến cục bộ. Làm thế nào an toàn là nó?

const std::string& ClassName::MethodName() const 
{ 
    return ""; 
} 

Trình biên dịch đưa ra một cảnh báo:

Cảnh báo C4172: trở về địa chỉ của biến cục bộ hoặc tạm thời

Tôi nghĩ trình biên dịch là đúng. Chức năng này an toàn đến mức nào?

Lưu ý rằng hàm không trả về const char*, điều này có thể được chấp nhận vì chuỗi ký tự chuỗi có thời lượng lưu trữ tĩnh. Nó trả về một tham chiếu đến const std::string

Trả lời

6

Có nó không an toàn.
Trả về địa chỉ của một biến địa phương hoặc tạm thời và dereferencing nó kết quả trong hành vi Undefined.

Như bạn đã nhận xét:
Có, tuổi thọ của giới hạn tạm thời đối với tham chiếu không đổi sẽ tăng lên cho đến khi vòng đời không đổi. Nhưng điều đó cần người gọi chấp nhận giá trị trả về trong tham chiếu const, Vì vậy, chính nó chức năng sẽ không an toàn.

Từ ++ Chuẩn C:
C++ 03 12,2 đối tượng tạm thời:

Bối cảnh thứ hai là khi một tài liệu tham khảo được ràng buộc với một tạm thời. Tạm thời mà tham chiếu được đóng thành quyển hoặc tạm thời mà là đối tượng hoàn chỉnh đến một subobject trong đó tạm thời được ràng buộc kéo dài tuổi thọ của các tài liệu tham khảo trừ khi được quy định dưới đây ...

Một tạm thời bị ràng buộc để một thành viên tham chiếu trong bộ khởi tạo của hàm dựng (12.6.2) vẫn tồn tại cho đến khi hàm khởi tạo xuất hiện. Một ràng buộc tạm thời với tham chiếu tham số trong một cuộc gọi hàm (5.2.2) tồn tại cho đến khi hoàn thành biểu thức đầy đủ chứa cuộc gọi. Một giới hạn tạm thời với giá trị trả về trong câu lệnh trả về hàm (6.6.3) vẫn tồn tại cho đến khi hàm số lần thoát

+0

Tôi đã suy nghĩ dọc theo các dòng kéo dài tuổi thọ của một giới hạn tạm thời thành tham chiếu const ... Ý tôi là, có thể nó *** là *** an toàn?Tôi muốn chắc chắn trước khi nói chuyện với nhà phát triển đã thêm chức năng –

+0

@Armen Tsirunyan, nó an toàn cho đến khi bạn gọi bất kỳ chức năng nào. và thậm chí nếu bạn không gọi hàm, bạn không thể sử dụng nó, bởi vì mọi thứ có thể sử dụng nó là một hàm. và thậm chí nếu bạn tìm cách sử dụng nó mà không có bất kỳ chức năng nào, trình biên dịch có thể sắp xếp lại mã của bạn và đặt một hàm ở giữa. vì vậy nó không an toàn trong bất kỳ cách nào – Dani

+0

@ Als: Tôi không thể nói rằng tôi hài lòng với câu trả lời. Nếu tuổi thọ của một lỗi tạm thời cục bộ không thể được mở rộng ra ngoài phạm vi của nó (mà tôi không biết nếu nó là trường hợp) thì bạn đã đúng, ** nhưng ** trong trường hợp này ràng buộc giá trị trả về của hàm đến tham chiếu const sẽ không giúp ích gì. Nếu nó có thể được mở rộng bên ngoài chức năng, thì nó không liên quan cho dù tôi có ràng buộc hay sao chép nó ... –

3

làm những gì bạn đã làm thực sự thực hiện điều này trong nội bộ trong trình biên dịch:

const std::string* ClassName::MethodName() const 
{ 
    std::string temp = ""; 
    return &temp; 
} 

Và trở về tài liệu tham khảo hoặc con trỏ đến các biến địa phương là xấu.

+0

Đó là nhiều hơn xấu - đó là * terribad *, không xác định. – Schnommus

1

Đây là một ví dụ mà làm cho mọi việc rõ ràng cho tôi:

#include <iostream> 
using std::cout; 
struct A{ 
    A() { 
     cout << "Ctor\n"; 
    } 
    ~A() { 
     cout << "Dtor\n"; 
    } 
}; 

const A& f(){ 
    return A(); 
} 

int main(){ 
    const A& ref = f(); 
    cout << "1\n"; 
    { 
     const A& ref1 = A(); 
     cout << "2\n"; 
    } 
    cout << "3\n"; 
} 

Đầu ra

Ctor 
Dtor 
1 
Ctor 
2 
Dtor 
3 
+0

Ví dụ bỏ lỡ điểm. Nếu bạn truy cập ref sau 3, nó sẽ có ý nghĩa hơn nhiều. –