2013-01-18 28 views
5

Tuyên bố từ chối trách nhiệm: Câu hỏi này dành cho sự hiểu biết. Tôi sẽ sử dụng boost::lexical_cast trong trường. It has sort of come up in the real world in places, though.Đây có phải là một thể hiện của tham chiếu đến không ràng buộc với một tạm thời không?


Hãy the following attempt tại một "inline" cách tiếp cận lex-cast:

#include <string> 
#include <sstream> 
#include <iostream> 

int main() 
{ 
    const std::string s = static_cast<std::ostringstream&>(
     std::ostringstream() << "hi" << 0 
    ).str(); 
    std::cout << s; 
} 

Kết quả là một cái gì đó giống như 0x804947c0, vì operator<< làm việc với "hi" là một chức năng miễn phí mà LHS phải mất std::ostream&& dagger; và tạm thời std::ostringstream() không thể liên kết với một ref-to-non const. Trận đấu còn lại duy nhất là operator<< mất const void* trên RHS & dagger; & dagger;.

Bây giờ let's swap the operands:

#include <string> 
#include <sstream> 
#include <iostream> 

int main() 
{ 
    const std::string s = static_cast<std::ostringstream&>(
     std::ostringstream() << 0 << "hi" 
    ).str(); 
    std::cout << s; 
} 

Kết quả là "0hi".

này chủ yếu có ý nghĩa, bởi vì operator<< rằng mất int là một hàm thành viên của cơ sở ostream& dao găm; & dao găm; & dao găm; và, như vậy, là tốt với được gọi trên tạm thời. Kết quả của hoạt động đó là tham chiếu đến cơ sở ostream, trong đó operator<< tiếp theo bị xích, tức là đọc nó là (std::ostringstream() << 0) << "hi".

Nhưng tại sao sau đó hoạt động trên "hi" tiếp tục mang lại kết quả mong đợi? Không phải là tài liệu tham khảo về LHS vẫn là tạm thời?


Hãy tập trung vào C++ 03; Tôi đã nói rằng ví dụ đầu tiên có thể thực sự hoạt động như "dự định" trong C++ 11 do toán tử catch-all cho các giá trị.

& dagger;[C++03: 27.6.2.1]: template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,charT*);

& dagger; & dagger;[C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(const void* p);

& dagger; & dagger; & dagger;[C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(int n);

+0

Tôi đoán câu trả lời là một cái gì đó dọc theo dòng "các quy tắc cho thời gian ràng buộc để tham chiếu là hư không gần đó đơn giản, đây là những cụm từ thích hợp". –

+0

Điều này làm việc cho cùng một lý do mà bạn có thể viết một mẫu chức năng 'mẫu T & lvalue (T && v) {return v;}' để ràng buộc các tham chiếu không phải const lvalue vào thời gian. – Mankarse

+0

Sẽ không phải là quá tải cho chú thích đầu tiên của bạn được những người mà mất 'const char [T] *'? (Không phải là nó thay đổi bất cứ điều gì.) – Mat

Trả lời

3

Lý do rất đơn giản. Nếu bạn đọc những câu hỏi tôi hỏi về:

std::ostringstream printing the address of the c-string instead of its content.

bạn sẽ lưu ý lừa để nhận được một "hợp lý" tài liệu tham khảo thay vì tạm thời là để gọi một phương thức trên đối tượng (không bị giới hạn để hạn chế không ràng buộc vì một lý do nào đó) sẽ trả về một tham chiếu.

Trong câu trả lời Nawaz của trên, mà ông gọi là std::ostream& std::ostream::flush(), trong trường hợp của bạn ở đây:

std::ostringstream() << 0 << "hi" 

bạn gọi std::ostringstream& std::ostringstream::operator<<(int).

Kết quả tương tự.

Hành vi đáng ngạc nhiên là do ostream triển khai mishmash: một số operator<< là phương pháp thành viên trong khi các phương thức khác là chức năng miễn phí.

Bạn có thể kiểm tra nó, đơn giản, bằng cách thực hiện một phương pháp X& ref() vào một đối tượng:

struct X { X& ref(); }; 

void call(X& x); 

int main() { 
    call(X{});  // error: cannot bind X& to a temporary 
    call(X{}.ref()); // OK 
} 

EDIT: nhưng tại sao không được X& (kết quả của ref) điều trị giống nhau không?

Đó là vấn đề của classification. Tạm thời là prvalue trong khi tham chiếu là lvalue. Tham chiếu chỉ được phép liên kết với một số lvalue. Tất nhiên vì các phương pháp có thể được gọi trên rvalue (và do đó prvalue) và các phương pháp đó có thể trả về một tham chiếu đến các đối tượng mà chúng được gọi trên chúng ta có thể dễ dàng bỏ qua (1) ngớ ngẩn. a lvalue hạn chế ...

(1) nó cũng không phù hợp với thực tế là rvalue có thể bị ràng buộc với tham chiếu const.

+1

Tôi không cảm thấy rằng điều này trả lời câu hỏi. Tôi biết về chức năng thành viên và chức năng miễn phí. Nhưng đối tượng vẫn là một tạm thời, vậy tại sao tham chiếu liên kết với nó ở cuối bởi vì nó đã được tạo ra bởi một lời gọi hàm? –

+0

@LightnessRacesinOrbit: một vấn đề 'lvalue' /' rvalue' đơn giản, tôi mở rộng câu trả lời của mình. Làm thế nào trình biên dịch có thể biết rằng 'X & X :: ref()' là một cá thể 'X' mà' ref' được gọi là? Nó không thể (nói chung), do đó, nó hoàn toàn dựa trên phân loại các loại. –

+0

Bản chỉnh sửa sẽ thực hiện; cảm ơn –

2

Không phải là tham chiếu về LHS vẫn là tạm thời?

Đây là tham chiếu lvalue với giá trị trả về tạm thời (giá trị trả về), vẫn là một giá trị và do đó có thể liên kết với tham chiếu giá trị lvalue.

Hãy nghĩ về thời gian tồn tại về mặt đời thay vì l/rvalueness.

+0

(bạn có thể biết điều này. Tôi đang nhầm lẫn với những gì bạn đang yêu cầu: S) – Pubby

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