2015-01-26 17 views
13

Có những trường hợp tôi muốn tham chiếu đến một đối tượng nhưng thay vào đó tôi nhận được một bản sao. Dưới đây là một ví dụ:Khi nào và tại sao tôi nhận được bản sao khi khởi tạo tham chiếu?

std::pair<const std::string, int> foo("hello", 5); 
    const std::pair<std::string, int> & bar = foo; 

    std::cout << "foo: " << foo.first << " " << foo.second << std::endl; 
    std::cout << "bar: " << bar.first << " " << bar.second << std::endl; 
    foo.second = 7; 
    std::cout << "foo: " << foo.first << " " << foo.second << std::endl; 
    std::cout << "bar: " << bar.first << " " << bar.second << std::endl; 

này tạo ra:

foo: hello 5 
bar: hello 5 
foo: hello 7 
bar: hello 5 

Vì vậy, rõ ràng là một bản sao của foo đã được tạo ra trong khi cú pháp gợi ý (với tôi ít nhất) mà các lập trình viên muốn có một tham chiếu đến nó . Điều này vi phạm nguyên tắc rằng tham chiếu phải là bí danh cho một điều gì đó. Sẽ thật tuyệt nếu ai đó có thể giải thích những gì đang diễn ra và tại sao.

(Lưu ý: Tôi đã xem qua này here)

+3

Các loại khác nhau. – Borgleader

Trả lời

15

Các loại cơ bản của foobar là khác nhau, do đó, một tạm thời được tạo ra sử dụng một chuyển đổi ngầm từ các loại trên RHS đến một trên LHS *. Tiêu chuẩn C++ cho phép tham chiếu const để liên kết tạm thời và kéo dài tuổi thọ của nó.

Tài liệu tham khảo constbar liên kết với tạm thời, là đối tượng riêng biệt từ foo.

Nếu bạn đã sử dụng các loại tương tự, bạn sẽ nhận được kết quả bạn mong đợi:

std::pair<const std::string, int> foo("hello", 5); 
const std::pair<const std::string, int> & bar = foo; 

hoặc

std::pair<std::string, int> foo("hello", 5); 
const std::pair<std::string, int> & bar = foo; 

sẽ mang lại

foo: hello 5 
bar: hello 5 
foo: hello 7 
bar: hello 7 

* std::pair có một số template constructor cho phép chuyển đổi tiềm ẩn này từ một loại cặp này sang cặp khác.

+1

Và trong trường hợp nào sẽ gán kiểu không tương thích tạo tạm thời thay vì chỉ ném một lỗi trình biên dịch? – Sarien

+0

@Sarien Có cần phải có một chuyển đổi hợp lệ giữa 'T1' và' T2' trong 'const T2 & = T1'; – juanchopanza

+0

@Sarien trình biên dịch tìm kiếm một chuyển đổi khả thi. Nó có thể gọi hàm tạo của 'cặp' với các bản sao của giá trị trong cặp ban đầu, vì vậy nó sẽ làm. –

5

Đó là thuộc tính đặc biệt của tham chiếu đến const (và tham chiếu rvalue, một cách tự nhiên). Các tham chiếu này có thể liên kết với các đối tượng tạm thời.

ý rằng std::pair<const std::string, int> (loại foo) là một loại khác với std::pair<std::string, int> (loại mà bar muốn tham khảo, modulo const). Không có đối tượng thuộc loại std::pair<std::string, int> trong mã của bạn, vì vậy bar không thể liên kết với bất kỳ đối tượng nào như vậy.

Tuy nhiên, như tôi đã nói, tham chiếu đến các tham chiếu const và rvalue có thể liên kết với thời gian. Và một đối tượng thuộc loại std::pair<std::string, int> có thể được tạo hoàn toàn từ một đối tượng thuộc loại std::pair<const std::string, int>. Do đó, một đối tượng tạm thời như vậy được tạo ra và bar bị ràng buộc với đối tượng đó tạm thời. Ràng buộc tham chiếu này cũng kéo dài thời gian tồn tại của tạm thời lên giá trị của bar*.

Đó là lý do bạn nhận được bản sao. Nếu bạn đã thay đổi loại bar thành std::pair<std::string, int> & (tức là đã giảm số const), thay vào đó bạn sẽ nhận được lỗi biên dịch là tham chiếu không phải l constue không thể liên kết với tạm thời.


* Trong trường hợp đặc biệt của một biến thành viên của kiểu tham chiếu ràng buộc với một tạm thời, tuổi thọ của tạm thời sẽ chỉ kéo dài cho đến khi kết thúc xây dựng mà khởi tạo các tài liệu tham khảo.

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