2012-09-07 36 views
17

thể trùng lặp:
Lifetime of temporariesGiá trị tham số tạm thời nằm ngoài phạm vi khi nào?

int LegacyFunction(const char *s) { 
    // do something with s, like print it to standard output 
    // this function does NOT retain any pointer to s after it returns. 
    return strlen(s); 
} 

std::string ModernFunction() { 
    // do something that returns a string 
    return "Hello"; 
} 

LegacyFunction(ModernFunction().c_str()); 

Ví dụ trên có thể dễ dàng được viết lại để sử dụng con trỏ thông minh thay vì chuỗi; Tôi đã gặp phải cả hai tình huống này nhiều lần. Dù sao, ví dụ trên sẽ xây dựng một chuỗi STL trong ModernFunction, trả về nó, sau đó nhận một con trỏ tới một chuỗi kiểu C bên trong đối tượng chuỗi, và sau đó chuyển con trỏ đó tới hàm kế thừa.

  1. Có một đối tượng chuỗi tạm thời tồn tại sau khi ModernFunction đã trả về. Khi nào nó ra khỏi phạm vi?
  2. Có thể cho trình biên dịch gọi c_str(), hủy đối tượng chuỗi tạm thời này và sau đó truyền con trỏ trỏ đến LegacyFunction không? (Hãy nhớ rằng đối tượng chuỗi đang quản lý bộ nhớ mà c_str() trả về các giá trị cho ...)
  3. Nếu mã trên không an toàn, tại sao nó không an toàn và có cách viết ngắn gọn hơn nó hơn là thêm một biến tạm thời khi thực hiện các cuộc gọi hàm? Nếu nó an toàn, tại sao?
+0

Tôi vừa biên soạn và nó hoạt động. Nó cũng sẽ hoạt động, theo câu trả lời của ForEveR. –

+2

@ H2CO3, "nó hoạt động" không bao giờ chứng minh bất cứ điều gì - đôi khi bạn chỉ nhận được may mắn. Nếu bạn đã thử nó và nó * không * làm việc, điều đó sẽ khác. –

+0

@MarkRansom nhận thấy "Nó cũng sẽ hoạt động, theo phần trả lời của ForEveR"? (để làm rõ: Tôi biết điều đó.) –

Trả lời

14
LegacyFunction(ModernFunction().c_str()); 

Tiêu hủy bản sao sẽ được sau khi đánh giá full expression (ví dụ: sau khi trở về từ LegacyFunction).

n3337 12,2/3

đối tượng tạm thời bị phá hủy như là bước cuối cùng trong việc đánh giá đầy đủ biểu thức (1.9) mà (giải nghĩa từ vựng) chứa các điểm mà họ đã tạo ra.

n3337 1,9/10

Một đầy đủ thể hiện là một biểu hiện đó không phải là một subexpression biểu hiện khác. Nếu một ngôn ngữ xây dựng được định nghĩa để tạo ra một cuộc gọi ngầm định của một hàm, việc sử dụng cấu trúc ngôn ngữ được coi là một biểu thức cho các mục đích của định nghĩa này. Một cuộc gọi đến một destructor được tạo ra vào cuối đời của một đối tượng khác với một đối tượng tạm thời là một biểu thức đầy đủ tiềm ẩn. Chuyển đổi được áp dụng cho kết quả của một biểu thức để đáp ứng các yêu cầu của cấu trúc ngôn ngữ trong đó biểu thức xuất hiện cũng được coi là một phần của biểu thức đầy đủ. [Ví dụ:

struct S { 
S(int i): I(i) { } 
int& v() { return I; } 
private: 
int I; 
}; 
S s1(1); // full-expression is call of S::S(int) 
S s2 = 2; // full-expression is call of S::S(int) 
void f() { 
if (S(3).v()) // full-expression includes lvalue-to-rvalue and 
// int to bool conversions, performed before 
// temporary is deleted at end of full-expression 
{ } 
} 

9

Có một đối tượng chuỗi tạm tồn tại sau khi ModernFunction đã trở lại. Khi nào nó ra khỏi phạm vi?

Nói chính xác, không bao giờ là trong phạm vi. Phạm vi là tài sản của một tên, không phải là một đối tượng.Nó chỉ xảy ra khi các biến tự động có liên kết rất chặt chẽ giữa phạm vi suốt đời. Các đối tượng không phải là biến tự động khác nhau.

Đối tượng tạm thời bị hủy ở cuối biểu thức đầy đủ mà chúng xuất hiện, với một vài ngoại lệ không có liên quan ở đây. Dù sao các trường hợp đặc biệt mở rộng toàn bộ thời gian tạm thời, chúng không giảm được.

Có thể cho trình biên dịch để gọi c_str(), hủy đối tượng chuỗi tạm này, và sau đó vượt qua một con trỏ tòn ten để LegacyFunction

Không, bởi vì toàn thể hiện là LegacyFunction(ModernFunction().c_str()) (trừ bán đại tràng: cảm thấy rằng người đi bộ), vì vậy tạm thời là giá trị trả lại của ModernFunction không bị hủy cho đến khi LegacyFunction đã trở lại.

Nếu an toàn, tại sao?

Vì tuổi thọ tạm thời đủ dài.

Nói chung với c_str, bạn phải lo lắng về hai điều. Đầu tiên, con trỏ nó trả về sẽ trở thành không hợp lệ nếu chuỗi bị hủy (đó là những gì bạn đang yêu cầu). Thứ hai, con trỏ nó trả về sẽ trở thành không hợp lệ nếu chuỗi được sửa đổi. Bạn đã không lo lắng về điều đó ở đây, nhưng nó là OK, bạn không cần phải, bởi vì không có gì thay đổi chuỗi hoặc.

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