2010-06-06 23 views
5

tôi đã cố gắng mã sau:đèo đối tượng tạm thời đến chức năng mà sẽ đưa con trỏ

#include<iostream> 
#include<string> 
using namespace std; 

string f1(string s) 
{ 
    return s="f1 called"; 
} 

void f2(string *s) 
{ 
    cout<<*s<<endl; 
} 

int main() 
{ 
    string str; 
    f2(&f1(str)); 
} 

Tuy nhiên, mã này không biên dịch.
Điều tôi nghĩ là: f1 trả về theo giá trị để nó tạo ra tạm thời, trong đó tôi lấy địa chỉ và chuyển đến f2.
Bây giờ hãy giải thích cho tôi nơi tôi đang nghĩ sai?

Trả lời

5

Unary & lấy một giá trị (hoặc tên hàm). Hàm f1() không trả về một giá trị, nó trả về một giá trị (đối với hàm trả về một giá trị nào đó, trừ khi nó trả về một tham chiếu, giá trị trả về của nó là một giá trị), vì vậy không thể áp dụng & đơn nhất cho nó.

+0

Nhưng tôi có thể sử dụng f1() như thế này: f1 (str) = "happy"; Ở đây tôi đang sử dụng tạm thời làm giá trị l. –

+4

Happy Mittal, từ lvalue có thể hơi khó hiểu - nó không còn có nghĩa là "một giá trị có thể đứng ở phía bên trái của bài tập". khi bạn sử dụng toán tử '=', bạn đang thực sự gọi một hàm thành viên của đối tượng chuỗi. Bạn được phép sử dụng các thành viên của rvalues. – avakar

+0

Vậy điều gì sẽ xảy ra nếu chuỗi có toán tử rõ ràng & {return this;}? – user168715

1

Chương trình của bạn không biên dịch vì f1 có thông số và bạn không chuyển bất kỳ thông số nào.

Ngoài ra, giá trị được trả về từ hàm là giá trị, bạn không thể lấy địa chỉ của hàm đó.

+0

Oh ... xấu của tôi. Nhưng nó vẫn đưa ra cảnh báo: "lấy địa chỉ tạm thời" –

+1

Happy Mittal, vâng, bởi vì nó là một giá trị. Hãy tưởng tượng hàm trả về 'int' thay vì một' chuỗi', nó có thể hiển nhiên hơn - giá trị được trả về không cần phải có vị trí bộ nhớ tương ứng. – avakar

1

Hãy thử điều này:

int main() 
{ 
    string str; 
    string str2 = f1(str); // copy the temporary 
    f2(&str2); 
} 
+1

Đó là một bản sao không cần thiết. (_Nếu bạn không nhớ sao chép chuỗi không cần thiết, tại sao lại bận tâm với C++?) Nếu bạn liên kết một giá trị với tham chiếu 'const', tuổi thọ của rvalue sẽ được kéo dài đến cuối thời gian tham chiếu. Vì vậy, 'const std :: string & str2 = f1 (str);' là những gì bạn muốn. – sbi

+0

@sbi: Ví dụ của tôi, giống như của anh ta, đơn giản hơn nhiều so với bất kỳ mã thế giới thực nào. – egrunin

+1

Lưu ý rằng câu trả lời của bạn là để dạy mọi người cách làm những điều họ chưa biết. Mặc dù bạn chỉ bỏ qua một cái gì đó bởi vì nó không liên quan đến lập luận của bạn, những người khác vẫn có thể nhận một thói quen sai từ nó. – sbi

3

Có thể tạo ra (và vượt qua) một con trỏ đến một đối tượng tạm thời, giả định rằng bạn biết những gì bạn đang làm. Tuy nhiên, nó nên được thực hiện khác nhau.

Một hàm có giá trị trả lại của loại không tham chiếu trả lại một rvalue. Trong C++, việc áp dụng toán tử unary & tích hợp vào một giá trị bị cấm. Nó đòi hỏi một lvalue.

Điều này có nghĩa, nếu bạn muốn lấy con trỏ đến đối tượng tạm thời của mình, bạn phải thực hiện theo cách khác. Ví dụ, như một hai dòng chuỗi

const string &r = f1(str); 
f2(&r); 

mà cũng có thể được xếp vào một dòng duy nhất bằng cách sử dụng một dàn diễn viên

f2(&(const string &) f1(str)); 

Trong cả hai trường hợp trên f2 chức năng nên chấp nhận một tham số const string *. Chỉ cần một string * như trong trường hợp của bạn sẽ không hoạt động, trừ khi bạn bỏ đi constness từ đối số (trong đó, BTW, sẽ làm cho toàn bộ điều thậm chí xấu hơn nó đã là). Mặc dù, nếu bộ nhớ phục vụ tôi, trong cả hai trường hợp, không có sự đảm bảo rằng tham chiếu được đính kèm với bản gốc tạm thời và không được sao chép.

Chỉ cần nhớ rằng việc tạo con trỏ đến các đối tượng tạm thời là một thực tế khá đáng ngờ vì nếu các vấn đề về tuổi thọ rõ ràng. Thông thường bạn nên tránh sự cần thiết phải làm điều đó.

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