Không hiểu bản chất của tham chiếu?
cho mình hỏi khi mình overload toán tử thì 2 câu lệnh sau đều làm thay đổi giá trị của đối tượng gọi nó:
PhanSo operator + (const PhanSo&); //1
PhanSo& operator += (const PhanSo&); //2
vậy dòng 1 không có dâu tham chiếu tại sao nó vẫn thay đổi được giá trị đối tượng, vd: a=a+b thì a sẽ thay đổi luôn.
nếu như vậy thì dấu tham chiếu ở dòng 2 có ý nghĩa gì?
vì mình thấy bản chất code của 2 dòng là giống nhau mà.
nhờ cộng đồng diễn đàn giải đáp thắc mắc giúp mình.
cảm ơn,
Thông
Bạn truyền tham chiếu của biến vào toán tử + qua tham số const PhanSo&
Trong hàm thực hiện thay đổi giá trị của PhanSo đó, và cái bạn trả về là giá trị của PhanSo sau khi đã thay đổi. Phân số kết quả được gán sau khi thực hiện phép cộng 2 phân số sẽ là gán giá trị, ko phải gán tham chiếu.
mình không hiểu lắm chỗ này, vd: a=a+b thì const PhanSo& chính là truyền tham chiếu của b vào chứ, còn a là đối tượng mình gọi mà.
mình vẫn chưa hiểu lắm câu trả lời của bạn.
Thế thì bạn coi lại việc truyền tham số cho phép cộng, phép cộng cần 2 toán hạng chứ không phải 1.
a=a.operator+(b);
vẫn 2 chứ nhỉ toán hạng 1 là cái đối tượng a mình gọi, b là thứ 2, nếu khi dùng friend mới truyền vào luôn 2 chứ .
operator là toán tử, không phải hàm, không dùng kiểu a.operator() được.
Mình sẽ giải thích về
Thực ra toán tử này không hề làm thay đổi đối tượng a lẫn b trong phép toán a = a + b;
Lý do làm a thay đổi là phép gán = thông operator=
a + b ở đây sẽ tạo ra một phần tử mới và phần tử này được gán ngược lại cho a thông qua phép gán a = a + b;
Các bạn phải đặc biệt chú ý trong khai báo operator phía trên:
Bạn thử sửa PhanSo& operator += (const PhanSo&); thành void operator += (const PhanSo&); rồi biên dịch và chạy thử xem, và suy nghĩ thử PhanSo& trả về để làm gì và khi nào nó cần thiết
PhanSo và PhanSo & về bản chất là giống nhau đều báo cho hàm (ở đây là toán tử operator) biết kiểu giá trị trả về là PhanSo
Vậy sự khác biệt của & là j, không lẽ viết vào cho code trông có vẻ pro hơn (ý kiến cá nhân: cái gì mà có & thì trông rất pro). Thực ra dùng than chiếu (&) để tránh việc gọi lại copy constructor. Nếu trong class phân số kia mà không có con trỏ thì PhanSo hoặc PhanSo & không có khác biệt nhiều. Ngược lại thì đó là một vấn đề hết sức đau đầu khi tìm lỗi.
P/S có j sai sót xin mọi người lượng thứ
ý bạn là chức năng mặc định của dấu = phải không (không phải overload lại)
theo mình biết là trả về tham chiếu phân số luôn , thông qua con trỏ this chẳng hạn, cần thiết vì mình đang update lại chính nó mà.
cảm ơn comment của bạn, giúp mình hiểu được chút vấn đề.
bạn giải thích rõ hơn chỗ này cho mình hiểu được không ?
khi bạn
return
thì sẽ trả về một bản sao. Cụ thể:Lúc này sẽ trả về bản sao của
KetQua
.Ngược lại nếu là:
Thì sẽ trả về chính cái
KetQua
mình vẫn không hiểu, theo mình biết thì KetQua khai báo bên trong phương thức này thôi, ra ngoài rồi nó cũng tự huỷ, thế thì làm sao nó trả về chính KetQua(trường hợp &) trong khi nếu nó đã gọi destructor.
Nó chỉ hủy sau khi thực hiện xong lệnh
return
.mình nghĩ nếu trả về chính địa chỉ của đối tượng gọi phương thức thì được, còn nếu là đối tượng KetQua như bạn thì lấy đâu vùng nhớ để hoạt động sau khi trả về.
Trường hợp trả về Reference mà BaoLe nêu lên thì Object đã bị hủy sau khi trả về nên reference trả về trỏ vào vùng nhớ đã được hủy. Tuyệt đối không nên sử dụng phương cách này!
Để hạn chế việc copy và tạo object mới khi thực hiện các toán tử không làm thay đổi giá trị của object nhận vào thì người ta thường dùng const Class& object;
Xem thử Implement toán tử +=:
Ở đây đối tượng trả về là chính bản thân nó nên hoàn toàn có thể sử dung reference, hơn nữa để có thể tiếp
tục sử dụng cho toán tử tiếp theo thì bắt buộc phải sử dụng reference trả về ở đây
VD: PhanSo a; a += b += c;
Để hiểu rõ hơn thì các bạn có thể thay kiểu trả về là PhanSo thay vì PhanSo& và chạy với ví dụ trên so sánh kết quả thử xem
trường hợp dùng tham chiếu:
cho em hỏi chỗ này có nghĩa là khi b+=c nó trả về tham chiếu của b, sau đó nó lấy tham chiếu đó (bản thân b) và tiếp tục với a+=b và trả về tham chiểu của a đúng không anh?
còn trường hợp không dùng tham chiếu thì em không hiểu được tại sao lại cộng liên tiếp như vậy được ?
cảm ơn anh.
Chính xác rồi bạn. Lúc dùng tham chiếu sẽ giảm số lượng copy contructor được gọi, do không cần tạo ra các đối tượng mới nữa.
Nhưng xét ví dụ này thử: (a += b) += c;
Ở đây nó thực hiện a += b trước sao đó tiếp tục cộng thêm c
Nếu dùng tham chiếu thì kết quả của a là: a = a + b +c;
Nếu dùng tham trị thì kết quả: a = a + b; vì phần (a += b) thay đổi giá trị của a và return về một đối tượng tạm thời đối tượng này thực hiên phép toán temp += c; sau đó temp bị huỷ
quá hay luôn. cảm ơn anh