Vietnamese Developers' Blog

Phân biệt pointer và reference

Posted in C/C++ by Hoang Tran on the October 22nd, 2007

(Nguồn: Item 1 – More Effective C++ – Scott Meyers)

Một câu hỏi interview khá phổ biến trong C++ là phân biệt giữa pointer và reference. Khi nào thì sử dụng pointer và khi nào thì sử dụng reference?. Pointer và reference thoạt nhìn thì thấy nó khác nhau nhưng dường như chúng đều làm những công việc giống nhau. Chúng đều cho phép chúng ta truy nhập gián tiếp vào một đối tượng khác.

Điểm đầu tiên có thể nhận ra rằng không có một cái nào được gọi là null reference (trong khi có null pointer). Có nghĩa là một reference phải luôn luôn refer đến một object nào đó. Do đó, nếu bạn có một biến mà mục đích của nó là refer đến một object nào đó nhưng nó có thể refer đến không object nào cả, thì bạn nên sử dụng pointer bởi vì sau đó bạn có thể cho giá trị của nó là null. Mặt khác, nếu biến đó phải luôn luôn refer đến một object (design không cho phép có khả năng biến đó là null) thì bạn nên để biến đó là reference.

Thế nhưng, trường hợp này thì sao

char *pc = 0;       // set pointer to null
char& rc = *pc;     // make reference refer to dereferenced null pointer

Đoạn code này thật nguy hiểm. Kết quả là không xác định (chương trình sẽ ra output mỗi lúc có thể khác nhau) và mọi người nên tránh những đoạn code kiểu này. Nếu bạn phải lo lắng về những thứ như vậy trong chương trình thì tốt nhất là bạn nên tránh sử dụng reference. Hoặc là như vậy hoặc là tìm kiếm một class tốt hơn mà lập trình viên có thể làm việc cùng.

Một reference phải refer đến một object nên C++ yêu cầu rằng reference phải được khởi tạo.

string& rs;     // error! References must be initialized

string s(”xyzzy”);
string& rs = s;     // okay, rs refers to s

Pointer thì thoải mái hơn nhiều

string *ps;     // uninitialized pointer: valid but risky

Thực tế là việc không có null reference nhiều khi làm cho việc sử dụng reference hiệu quả hơn sử dụng pointer, bởi vì không chúng ta không cần phải kiểm tra sự hợp lệ của reference trước khi sử dụng chúng:

void printDouble( const double& rd )
{
    cout << rd; // no need to test rd; it must refer to a double
} 

Mặt khác với pointer, chúng ta phải thường xuyên kiểm tra chúng có khác null hay không

void printDouble( const double *pd )
{
    if (pd) {   // check for null pointer
        cout << *pd;
    }
}

Một điểm khác biệt quan trọng khác giữa pointer và reference là pointer có thể được gán lại để refer đến một object khác. Tuy nhiên thì reference phải luôn luôn refer đến một object mà nó đã được khởi tạo:

string s1(”Nancy”);
string s2(”Clancy”);

string& rs = s1;    // rs refers to s1

string *ps = &s1;   // ps points to s1

rs = s2;        // rs still refers to s1, but s1’s value is now “Clancy”
ps = &s2;       // ps now points to s2; s1 is unchanged

Nói chung, bạn nên sử dụng con trỏ bất cứ khi nào bạn cần xem xét khả năng mà nó không refer đến gì cả (trường hợp mà bạn có thể cho con trỏ là null) hoặc bất cứ khi nào bạn cần khả năng refer đến những object khác nhau tại những thời điểm khác nhau (trường hợp mà bạn có thể thay đổi đối tượng con trỏ trỏ vào). Bạn nên sử dụng reference bất cứ khi nào có một object mà nó refer đến và bạn cũng biết rằng một khi nó đã refer đến object đó thì nó sẽ không thay đổi để refer đến một object khác.

Cũng có một tình huống khác mà bạn nên sử dụng reference, đó là khi bạn implement một toán tử. Ví dụ phổ biến nhất là toán tử []. Toán tử này cần phải trả về một thứ mà có thể sử dụng như đích của phép gán.

vector<int> v(10);  // create an int vector of size 10;
v[5] = 10;      // the target of this assignment is the return value of operator[] 

Nếu operator[] trả về một pointer thì lệnh gán phải được viết như sau:

*v[5] = 10; 

Nhưng nó nhìn giống như là v là một vector of pointers trong khi không phải như vậy. Vì lý do này mà bạn luôn muốn operator[] trả về một reference (tuy nhiên vẫn có một ngoại lệ thú vị được đề cập trong Item 30 – More Effective C++)

Tagged with: , ,

One Response to 'Phân biệt pointer và reference'

Subscribe to comments with RSS or TrackBack to 'Phân biệt pointer và reference'.

  1. Cuong Bui said, on April 7th, 2010 at 10:30 am

    Good entry!

    Thanks

Leave a Reply