2012-02-15 16 views
40

Tôi đã đọc ở khắp mọi nơi rằng một tài liệu tham khảo phải được khởi tạo sau đó và ở đó và không thể được tái khởi tạo lại.Chúng tôi có thể chỉ định lại tham chiếu trong C++ không?

Để kiểm tra hiểu biết của mình, tôi đã viết chương trình nhỏ sau đây. Có vẻ như tôi đã thực sự thành công trong việc chỉ định lại một tham chiếu. Ai đó có thể giải thích cho tôi những gì đang thực sự xảy ra trong chương trình của tôi không?

#include <iostream> 
#include <stdio.h> 
#include <conio.h> 

using namespace std; 

int main() 
{ 
    int i = 5, j = 9; 

    int &ri = i; 
    cout << " ri is : " << ri <<"\n"; 

    i = 10; 
    cout << " ri is : " << ri << "\n"; 

    ri = j; // >>> Is this not reassigning the reference? <<< 
    cout << " ri is : " << ri <<"\n"; 

    getch(); 
    return 0; 
} 

mã biên dịch tốt và đầu ra là như tôi mong đợi:

ri is : 5 
ri is : 10 
ri is : 9 

Trả lời

42

ri = j; // >>> Is this not reassigning the reference? <<<

Không, ri vẫn là một tham chiếu đến i - bạn có thể chứng minh điều này bằng cách in &ri&i và nhìn thấy họ đang cùng một địa chỉ.

Việc bạn đã làm là sửa đổi ithông qua tham chiếu ri. In i sau và bạn sẽ thấy thông báo này.

Ngoài ra, để so sánh, nếu bạn tạo const int &cri = i; nó sẽ không cho phép bạn gán cho điều đó.

+0

Tại sao 'const int & cri = i' không được phép? Bạn không thể viết dòng nào? Nguyên nhân cho tôi trình biên dịch cho phép chèn dòng như vậy ở bất kỳ nơi nào. Ngoài ra, đó là một câu trả lời rõ ràng và ngắn gọn! – mercury0114

+0

Tôi đã không nói rằng không được phép - như bạn quan sát, tham gia một const ref cho một biến không const là tốt. Tôi đã nói nó sẽ không cho phép bạn gán cho điều đó, nghĩa là bạn không thể thay đổi biến ban đầu thông qua một tham số const, như OP đã làm với 'ri'. – Useless

+0

Ồ đúng rồi, giờ tôi thấy ý của bạn là gì. – mercury0114

3

Khi bạn gán một cái gì đó để tham khảo bạn thực sự gán giá trị cho các đối tượng tham chiếu là ràng buộc để. Vì vậy, đây:

ri=j; 

có tác dụng tương tự như

i = j; 

sẽ phải vì ri là ràng buộc để i. Vì vậy, bất kỳ hành động nào trên ri được thực hiện trên i.

3

Bạn không được chỉ định lại tham chiếu khi thực hiện ri = j;. Bạn đang thực sự chỉ định j đến i. Hãy thử in i sau dòng và bạn sẽ thấy rằng i giá trị thay đổi.

6

Có vẻ như tôi đã thực sự thành công trong việc chỉ định lại tham chiếu. Điều đó có đúng không?

Không, bạn chưa có. Bạn đang thực sự chỉ định lại giá trị, và bạn không trả lại tham chiếu.

Trong ví dụ của bạn, khi bạn thực hiện int &ri = i;, ri bị ràng buộc là i cho toàn bộ thời gian tồn tại của nó. Khi bạn thực hiện ri = j;, bạn chỉ cần chỉ định giá trị của j đến ri. ri vẫn là tham chiếu đến i! Và kết quả là kết quả tương tự như thể bạn đã viết thay vì bằng văn bản i = j;

Nếu bạn hiểu rõ con trỏ, hãy luôn xem tham chiếu là cách diễn giải tương tự T* const trong đó T là bất kỳ loại nào.

0

OP yêu cầu thay đổi đối tượng được tham chiếu thông qua gán cho tham chiếu và được thông báo chính xác rằng điều này đã thay đổi đối tượng tham chiếu, chứ không phải tham chiếu. Bây giờ tôi đã làm một nỗ lực sâu sắc hơn tại thực sự thay đổi các tài liệu tham khảo và tìm thấy những thứ có khả năng khó chịu. Đầu tiên là mã. Nó cố gắng gán lại tham chiếu var một đối tượng mới được tạo, sau đó thay đổi đối tượng tham chiếu aka tham chiếu, thấy rằng điều này không được phản ánh trong các đối tượng được tham chiếu rõ ràng và kết luận rằng chúng ta có thể có một trường hợp con trỏ lơ lửng trong C++. Xin lỗi vì mã được viết vội vàng.

using namespace std; 
vector<int>myints; 

auto &i = myints.emplace_back(); // allocate and reference new int in vector 
auto myintsaddr = &myints; auto myintfrontaddr = &myints.front(); // for future reference 
i = 1;        // assign a value to the new int through reference 
cout << hex << "address of i: 0x" << &i << " equals " << "address of 
myints.back(): 0x" << &myints.back() << '.' << endl; // check reference as expected 
i = myints.emplace_back();  // allocate new int in vector and assign to old reference variable 
i = 2;       // give another value to i 
cout << "i=" << i << ", myints={" << myints[0] << ", "<< myints[1] << '}' << endl; // any change to potentially referenced objects? 
cout << hex << "&i: 0x" << &i << " unequal to " << "&myints.back(): 0x" << &myints.back() << " as well as &myints.front(): 0x" << &myints.front() << endl; 
cout << "Myints " << (myintsaddr== &myints?"not ":"") << "relocated from " << myintsaddr << " to " << &myints << endl; 
cout << "Myints front() " << (myintfrontaddr == &myints.front() ? "not " : "") << "relocated from " << myintfrontaddr << " to " << &myints.front() << endl; 

Output:

address of i: 0x0063C1A0 equals address of myints.back(): 0x0063C1A0. 
i=2, myints={1, 0} 
&i: 0x0063C1A0 unequal to &myints.back(): 0x0063F00C as well as &myints.front(): 0x0063F008 
Myints not relocated from 0039FE48 to 0039FE48 
Myints front() relocated from 0063C1A0 to 0063F008 

Kết luận: ít nhất là trong trường hợp của tôi (VS2017) tài liệu tham khảo đã giữ địa chỉ chính xác tương tự trong bộ nhớ, nhưng các giá trị tham chiếu (một phần của vector) đã được phân bổ lại ở nơi khác. Tài liệu tham khảo tôi có thể đang lúng túng.

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