2012-02-29 42 views
17

Tôi quyết định xem liệu việc gán tham chiếu cho một thành viên sẽ làm cho thành viên trở thành tham chiếu hay không. Tôi đã viết đoạn mã sau để kiểm tra nó. Có một lớp đơn giản Wrapper với một biến số thành viên là std::string. Tôi lấy một số const string& trong hàm tạo và gán nó cho biến thành viên công khai. Sau đó trong phương pháp main() tôi sửa đổi biến thành viên nhưng string tôi chuyển cho hàm tạo vẫn không thay đổi, làm thế nào đến? Tôi nghĩ rằng trong Java biến sẽ thay đổi, tại sao không trong đoạn mã này? Các tham chiếu hoạt động chính xác như thế nào trong trường hợp này?Đi qua tham chiếu đến một hàm tạo

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

class Wrapper 
{ 
public: 
    string str; 

    Wrapper(const string& newStr) 
    { 
     str = newStr; 
    } 
}; 

int main (int argc, char * const argv[]) 
{ 
    string str = "hello"; 
    cout << str << endl; 
    Wrapper wrapper(str); 
    wrapper.str[0] = 'j'; // should change 'hello' to 'jello' 
    cout << str << endl; 
} 
+2

Các loại trong C++ là những gì bạn quyết định và chúng không trở thành một thứ gì đó kỳ diệu. Bạn nói 'string', và bạn nhận được một' chuỗi'. Nếu bạn muốn tham khảo, bạn đã nói 'string &'. –

+0

Bạn lạm dụng những người có câu hỏi quá đơn giản :) – Mikhail

+2

Trong Java biến sẽ không thay đổi vì mã thậm chí sẽ không biên dịch; các chuỗi trong Java không được phép sửa đổi. –

Trả lời

22

Để gán một tham chiếu trong một constructor bạn cần phải có một thành viên tham khảo

class A{ 
    std::string& str; 
public: 
    A(std::string& str_) 
    : str(str_) {} 
}; 

str bây giờ là một tham chiếu đến các giá trị mà bạn thông qua vào. Tương tự áp dụng cho refs const

class A{ 
    const std::string& str; 
public: 
    A(const std::string& str_) 
    : str(str_) {} 
}; 

Tuy nhiên đừng quên rằng một khi một tham chiếu đã được gán, nó không thể thay đổi được, do đó nếu việc gán yêu cầu thay đổi thành str thì nó sẽ phải là một con trỏ thay thế.

5

Wrapper::str không phải là một tham chiếu, nó là một đối tượng độc lập. Vì vậy, khi bạn thực hiện str = newStr, bạn đang sao chép chuỗi.

1

Bạn nên khai báo Wrapper::str dưới dạng string&, không phải là string.

3

Bạn cần phải sử dụng một initializer và tuyên bố str như một tài liệu tham khảo như trong:

class Wrapper { 
public: 
    string &str; 

    Wrapper(string& newStr) 
     : str(newStr) { 
    } 
}; 

Cách bạn đang viết nó, tất cả các bạn đang làm là sao chép các giá trị của các tài liệu tham khảo để bạn vượt qua các constuctor . Bạn không lưu tham chiếu. Bằng cách khai báo một tham chiếu như một thành viên lớp và khởi tạo nó với một tham chiếu đến một cá thể chuỗi khác, bạn sẽ nhận được hành vi mà bạn đang tìm kiếm.

+1

Mã của bạn cố gắng khởi tạo tham chiếu có thể thay đổi bằng tham chiếu đến const. –

+0

Đã sửa lỗi ... đó là những gì tôi nhận được để sao chép một cách mù quáng từ OP. – andand

5
class Wrapper 
{ 
public: 
    string& str; 

    Wrapper(string& newStr) : str(newStr) {} 
}; 

Lưu ý, bạn không thể chấp nhận một const string& và lưu nó trong một string&, bạn sẽ mất const-đúng đắn khi làm như vậy.

1

Biến chính của bạn là std::string.

Biến thông số của bạn là const std::string&.

const trong tham chiếu luôn là "mức độ thấp const", có nghĩa là nó sửa đổi loại đối tượng không phải là đối tượng thực tế.

Ngược lại, "const cấp cao nhất" sửa đổi một đối tượng thực tế. Đọc C++ Primer on Top level const để làm rõ.

Sau đây là cách phân công của bạn trông giống như khi bạn vượt qua đối số:

const std::string& = std::str; //Values are ommited 
// i.e const std::string newStr = std::string str 

Bạn đang khởi tạo một const type reference với một non-const value đó là chấp nhận được. Bạn không được phép thay đổi giá trị của std::string str bằng cách sử dụng tham chiếu đó.Và, nếu bạn thử thay đổi giá trị của newStr bên trong hàm tạo, bạn sẽ nhận được lỗi biên dịch.

Tiếp theo bạn đang làm một nhiệm vụ bên trong các nhà xây dựng mà cũng có thể chấp nhận:

std::string = const std::string 

Thực tế là wrap.str[0] không thay đổi str của main là, mặc dù một tài liệu tham khảo đã được sử dụng để nhanh chóng class str, class str có đối tượng riêng và không được liên kết với main str. Sử dụng tham chiếu đó trong tham số chỉ liên kết thông số đó với main str; không phải main str đến class str.

Nếu biến lớp của bạn được tham chiếu, thì biến đó có thể đã thay đổi.

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