2012-10-18 8 views
7

Tôi đã có một cơ bản C++ câu hỏi khá, hãy xem xét một hàm mang theo một số thông số đầu vào và tạo ra một std::string rằng từ những thông số như hình dưới đây:C++ trở về đối tượng tạm thời nhầm lẫn

std::string constructString(int some_parameter) { 

    std::stringstream ss; 

    // Construct a string (arbitrarily complex) 
    ss << "Some parameter is " << some_parameter << " right now"; 

    return ss.str(); //Am I not returning a temporary object here? 
} 

Tôi hiểu rằng stringstream-object sẽ đi ra khỏi phạm vi khi hàm trả về, nhưng nó không làm mất hiệu lực chuỗi được xây dựng?

Điều gì sẽ xảy ra nếu tôi thay đổi loại trả về thành const char * và trả lại ss.str().c_str() thay thế?

Mã như trên dường như làm việc, nhưng tôi nghi ngờ đó chỉ là vì bộ nhớ có chứa các đối tượng 'tạm thời' vẫn chưa được ghi đè bằng cái gì khác khi tôi sử dụng nó?

Tôi phải thừa nhận, tôi khá bối rối trong những tình huống như vậy nói chung, tôi đánh giá cao nếu ai đó có thể giải thích toàn bộ "đối tượng tạm thời" này cho tôi (hoặc chỉ cho tôi đi đúng hướng).

thx trước

Trả lời

10

Bạn đang trả về một đối tượng tạm thời, nhưng vì bạn trả lại theo giá trị, bản sao được tạo. Nếu bạn trả về con trỏ hoặc tham chiếu đến đối tượng tạm thời, đó sẽ là một sai lầm.

Nếu bạn thay đổi kiểu trả về thành const char * và trả về ss.str().c_str(), bạn sẽ trả về con trỏ tới một số vùng đệm tạm thời std::string được trả lại bởi ss.str() và điều đó sẽ rất tệ.

2

Như bạn thấy Stringstream::str() lợi nhuận std::string đối tượng. Bạn trả std::string mà không cần tham khảo đó có nghĩa rằng nếu không có RVO (NRVO) tối ưu hóa constructor sao chép sẽ gọi và tạo đối tượng hợp lệ std::string. Với tối ưu hóa std::string sẽ được di chuyển mà không cần hàm tạo bản sao. Nhưng nếu sẽ trả lại std::string&, nó sẽ sụp đổ vì đối tượng này sẽ bị hủy sau khi trả về hàm. Cùng hiệu ứng sẽ được với const char * vì sau khi tiêu diệt con trỏ này sẽ chỉ vào bộ nhớ xấu và đây là tình huống nguy hiểm.

+0

Sẽ là destructor được gọi là sau khi bản sao này sẽ không được chọn bằng cách gọi hàm constructString? Vì nó là đối tượng tạm thời, tôi giả sử con trỏ đến nó được giữ trên stack như một giá trị trả về. Điều gì sẽ xảy ra sau khi nó được trả lại? Nó bị phá hủy nếu không có chủ sở hữu đối tượng mới? Làm thế nào trình biên dịch biết rằng đối tượng phải được tiêu huỷ hay không sau khi nó được trả về? –

1

Giả sử điều này: T val = some_function(), khi bạn trả lại giá trị từ some_function Giá trị sao chép C++ của giá trị trả về thành val bằng cách sử dụng hàm tạo bản sao được chỉ định hoặc toán tử tích hợp. Vì vậy, nếu bạn quay lại một int hay std::string không có vấn đề gì cả, nhưng nếu bạn trả về một con trỏ đến một ký ức đó sẽ được trả tự do vào cuối của hàm, oops !! con trỏ của bạn sẽ được trỏ đến bộ nhớ không hợp lệ. Ví dụ xem xét việc này:

const char* some_function() { 
    std::string res(...); 
    //... 
    return res.c_str(); 
} 

Bạn đang quay trở lại con trỏ đến dữ liệu đó sẽ được giải phóng càng sớm càng hàm trả về (vì res sẽ bị phá hủy và nó sẽ giải phóng dữ liệu nội bộ của mình), do đó bạn sẽ nhận được địa chỉ, nhưng điều đó địa chỉ không trỏ đến những gì bạn có thể mong đợi!

+0

* "Giá trị sao chép C++ của giá trị trả về vào val" * - Thậm chí nhiều hơn thế, nó đã sao chép giá trị trả về 'ss.str()' vào giá trị trả về của hàm, bởi vì anh ta trả về giá trị. Vì vậy, nó thậm chí sẽ làm việc với 'const T & val = some_function()', cho 'some_function' trả về giá trị. –

+1

'const T & val = some_function()' thực sự hoạt động hoàn hảo, vì C++ sao chép mọi thứ theo giá trị và 'const T &' thực sự là 'const T *' với một số ngữ nghĩa khác nhau, vấn đề ở đây là 'const T &' trỏ đến một vị trí sẽ bị vô hiệu sau khi cuộc gọi chức năng hoàn tất! – BigBoss

+1

Không, nó sẽ không, bởi vì ràng buộc một tham chiếu const để tạm thời kéo dài tuổi thọ của tạm thời. Đó là lý do tại sao 'void foo (const std :: string &); foo ("test"); 'hoạt động hoàn toàn ổn. Nó sẽ không làm việc cho một con trỏ (hoặc một tham chiếu không const), mặc dù. Đây là một trong những khác biệt nhỏ, mà làm cho tài liệu tham khảo thực sự cái gì khác hơn so với cú pháp đường cho con trỏ. –