Tôi xin giải thích vấn đề trên như sau:
- Truyền biến cho hàm theo tham trị: rất nhiều các trình biên dịch gọi bộ tạo copy của biến và truyền nó cho hàm còn 1 số thì lưu lại giá trị của biến, hết hàm thì lưu ngược trở lại giá trị của biến->không thể thay đổi được giá trị biến truyền cho hàm trong hàm đó.
- Truyền biến theo tham chiếu: biến được truyền thật sự, bất cứ thay đổi về biến nào trong hàm cũng dẫn tới thay đổi giá trị của biến. Muốn không thay đổi giá trị thì chuyển theo tham chiếu đến const.
Còn đây là phần phân tích:
Theo mặc định, C++ truyền các đối tượng qua hàm theo tham trị(do thừa kế từ C). Trừ phi bạn xác định theo cách khác, điều này có thể rất tốn kém. VD xem xét hệ thống phân cấp sau:
class Person{
public:
Person();//tôi loại bỏ tham số cho đơn giản
virtual ~Person;//do lớp này là lớp cơ sở đa hình->phải làm hàm hủy thành ảo
...//các cài đặt khác
private:
std::string name;
std::string address;
};
class Student:public Person{
public:
Student();//tôi loại bỏ tham số cho đơn giản
~Student();
...//các cài đặt khác
private:
std::string schoolName;
std::string schoolAddress;
};
Bây giờ xem xét mã sau đây, trong đó chúng ta gọi một hàm validateStudent, hàm này lấy một đối số Student theo tham trị và trả về kết quả cho thấy nó đã được hiệu lực hóa 0:
bool validateStudent(Student s);
Student syd;
bool sydOK=validateStudent(syd);
Như bạn dễ dàng phân tích, sẽ cần tới 6 bộ tạo và 6 bộ hủy để tạo ra một đối tượng Student s từ syd. Quá tốn kém!
Còn với truyền theo tham chiếu đến const thì hiệu quả hơn nhiều do các bộ tạo và hủy không được gọi:
bool validateStudent(const Student&s)
Do validateStudent sẽ được thiết kế chỉ để kiểm tra chứ không phải sửa đối tượng Student->cần truyền tham chiếu đến const.
Việc truyền theo tham chiếu->const cũng tránh vấn đề cắt lát đối tượng. VD bạn làm việc trên một tập hợp lớp để thực thi một hệ thống cửa sổ:
class Window{
public:
...
std::string name() const;//trả về tên cửa sổ
virtual void display() const;//vẽ cửa sổ và dữ liệu
};
class WindowWithScrollBars:public Window{
public:
...
virtual void display const;
};
Giờ giả sử bạn muốn viết 1 hàm để in ra tên của 1 cửa sổ và sau đó hiển thị nó. Bạn hãy xem mã sai sau đây:
void printNameAndDisplay(Window w)
{
std::cout<<w.name();
w.display();
}
Xem xét những gì xảy ra khi bạn gọi hàm này với 1 đối tượng WindowWithScrollbars:
WindowWithScrollbars wwsb;
printNameAndDisplay(wwsb);
Điều gì xảy ra? Đối tượng wwsb sẽ bị cắt lát, wwsb.display() sẽ không gọi ...
còn nữa...
|