2011-07-31 33 views
10

Tôi cảm thấy câu hỏi này đủ cơ bản để có mặt ở đâu đó, nhưng dường như tôi không thể tìm ra câu trả lời cho nó.Khai báo một tham chiếu đến đối tượng và toán tử gán

Giả sử tôi có mã này:

//class member function 
std::map< std::string, std::string > myMap; 

const std::map< std::string, std::string >& bar() 
{ 
    return myMap; 
} 

void myFunc(std::map< std::string, std::string >& foo1) 
{ 
    foo1 = bar(); 
    std::map< std::string, std::string >& foo2 = bar(); 
} 

hiểu biết của tôi là nếu tôi bắt đầu sử dụng foo2, vì foo2 là một tham chiếu đến các trường hợp tương tự như những gì bar() trả về, bất cứ điều gì tôi làm với foo2 sẽ được phản ánh trong myMap. Nhưng còn foo1 thì sao? Foo1 có nhận được một bản sao của myMap hay không nó cũng trỏ đến cùng một ví dụ như những gì bar() trả về? Thư viện chuẩn C++ nói rằng toán tử gán cho std :: map sẽ sao chép các phần tử trên, nhưng điều đó có nghĩa là toán tử gán không thực sự được gọi trong khai báo của foo2?

Cảm ơn!

Trả lời

15

Tài liệu tham khảo không được lặp lại trong C++. Điều này có nghĩa là khi chúng được khởi tạo, bạn không thể gán lại chúng. Thay vào đó, bất kỳ phép gán nào thực sự liên quan đến đối tượng được gọi. Vì vậy, trong mã của bạn,

foo1 = bar(); 
std::map< std::string, std::string >& foo2 = bar(); 

dòng đầu tiên gọi std::map::operator= trên đối tượng đó đã được thông qua như một tham số để myFunc. Sau đó, foo1 ảnh tĩnh đề cập đến cùng một đối tượng đó - nhưng giá trị của nó (ví dụ: những yếu tố mà nó nắm giữ) có thể rất tốt đã được thay đổi.

Lưu ý rằng dòng thứ hai là không được gán nếu có bất kỳ nghi ngờ nào trong tâm trí bạn. Thay vào đó, nó là một khởi tạo. Vì kiểu trả về của thanh thực sự là std::map<std::string, std::string> const&, nó không thể liên kết với std::map<std::string, std::string>& do đó nó là một lỗi biên dịch.


Để mở rộng khía cạnh 'triết học', tài liệu tham khảo C++ được thiết kế minh bạch nhất có thể và không thực sự tồn tại dưới dạng đối tượng. Điều này đang sử dụng ý nghĩa C++ Standard của thuật ngữ (nó không liên quan đến OOP): điều đó có nghĩa là đối với các kiểu tham chiếu ví dụ, hãy làm không có kích thước. Thay vào đó, sizeof(T&) == sizeof(T). Tương tự, tài liệu tham khảo không có địa chỉ và không thể tạo con trỏ hoặc tham chiếu đến tham chiếu: được cung cấp int& ref = i;, sau đó &ref == &i.

Tham chiếu do đó có mục đích được sử dụng như thể các đối tượng được giới thiệu đang được sử dụng. Điều duy nhất tham chiếu cụ thể xảy ra trong vòng đời của một tham chiếu là khởi tạo của nó: những gì nó có thể liên kết với và ý nghĩa của nó về tuổi thọ.

+0

+1 Cảm ơn bạn, tôi đã học được điều gì đó mới mẻ. Tôi vừa thực hiện một thử nghiệm và tôi thực sự hoàn toàn là 100% WRONG và bạn đúng = -) – flumpb

+0

Ok tuyệt vời! Cảm ơn, những gì tôi thực sự cần biết là toán tử gán được gọi trong foo1 và không được gọi trong foo2. Lời giải thích tuyệt vời, cảm ơn! – bhh1988

+0

@Luc Nếu có thể, bạn có thể đi qua tại sao các biến tham chiếu thường không được sử dụng?Tôi có một sự hiểu biết tốt hơn về những gì họ đang có (nhờ câu trả lời của bạn) nhưng có vẻ như lập trình viên thường ủng hộ con trỏ trên nó. Nó là sự dư thừa? Phạm vi giới hạn? –

0

Dòng

foo1 = bar(); 

tạo ra một bản sao (vì đó là những gì toán tử gán map 's làm).

+0

có vẻ lạ để trả lại tham chiếu đến biến toàn cục, phải không? –

+0

@ 0A0D: Không thực sự, nó có thể được sử dụng để đóng gói, nếu biến "toàn cầu" không thực sự có liên kết bên ngoài. Hoặc bạn có thể trả về tham chiếu đến biến toàn cầu 'a' hoặc biến toàn cục' b'. –

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