Hãy để tôi thử và trả lời điều này quá.
Con trỏ tương tự như tài liệu tham khảo. Nói cách khác, chúng không phải là bản sao, mà là một cách để chỉ giá trị ban đầu.
Trước bất cứ điều gì khác, một nơi mà bạn thường sẽ phải sử dụng con trỏ rất nhiều là khi bạn đang xử lý phần cứng nhúng . Có lẽ bạn cần chuyển trạng thái của chân IO kỹ thuật số. Có thể bạn đang xử lý một ngắt và cần lưu trữ một giá trị tại một vị trí cụ thể. Bạn nhận được hình ảnh. Tuy nhiên, nếu bạn không trực tiếp xử lý phần cứng và chỉ đang phân vân không biết nên sử dụng loại nào, hãy đọc tiếp.
Tại sao sử dụng con trỏ trái ngược với các biến thông thường? Câu trả lời trở nên rõ ràng hơn khi bạn xử lý các loại phức tạp, như các lớp, cấu trúc và mảng. Nếu bạn sử dụng một biến thông thường, cuối cùng bạn có thể tạo một bản sao (trình biên dịch đủ thông minh để ngăn chặn điều này trong một số trường hợp và C ++ 11 cũng giúp, nhưng chúng ta sẽ tránh xa cuộc thảo luận đó ngay bây giờ).
Bây giờ điều gì xảy ra nếu bạn muốn sửa đổi giá trị ban đầu? Bạn có thể sử dụng một cái gì đó như thế này:
MyType a; //let's ignore what MyType actually is right now.
a = modify(a);
Điều đó sẽ hoạt động tốt và nếu bạn không biết chính xác lý do tại sao bạn sử dụng con trỏ, bạn không nên sử dụng chúng. Coi chừng lý do "có lẽ họ nhanh hơn". Chạy thử nghiệm của riêng bạn và nếu chúng thực sự nhanh hơn, sau đó sử dụng chúng.
Tuy nhiên, giả sử bạn đang giải quyết vấn đề cần phân bổ bộ nhớ. Khi bạn phân bổ bộ nhớ, bạn cần phải phân bổ nó. Việc cấp phát bộ nhớ có thể hoặc không thể thành công. Đây là nơi con trỏ trở nên hữu ích - chúng cho phép bạn kiểm tra sự tồn tại của đối tượng bạn đã phân bổ và chúng cho phép bạn truy cập vào đối tượng mà bộ nhớ được cấp phát bằng cách hủy tham chiếu con trỏ.
MyType *p = NULL; //empty pointer
if(p)
{
//we never reach here, because the pointer points to nothing
}
//now, let's allocate some memory
p = new MyType[50000];
if(p) //if the memory was allocated, this test will pass
{
//we can do something with our allocated array
for(size_t i=0; i!=50000; i++)
{
MyType &v = *(p+i); //get a reference to the ith object
//do something with it
//...
}
delete[] p; //we're done. de-allocate the memory
}
Đây là chìa khóa lý do tại sao bạn sẽ sử dụng con trỏ - các tham chiếu giả định rằng phần tử bạn tham chiếu đã tồn tại . Một con trỏ không.
Lý do khác khiến bạn sử dụng con trỏ (hoặc ít nhất là cuối cùng phải xử lý chúng) là vì chúng là loại dữ liệu tồn tại trước khi tham chiếu. Do đó, nếu bạn kết thúc việc sử dụng các thư viện để làm những việc mà bạn biết họ giỏi hơn, bạn sẽ thấy rằng rất nhiều thư viện này sử dụng con trỏ ở khắp mọi nơi, đơn giản là vì họ đã ở đây bao lâu (rất nhiều trong số họ đã được viết trước C ++).
Nếu bạn không sử dụng bất kỳ thư viện nào, bạn có thể thiết kế mã theo cách mà bạn có thể tránh xa các con trỏ, nhưng cho rằng các con trỏ là một trong những loại ngôn ngữ cơ bản, bạn càng cảm thấy thoải mái khi sử dụng chúng, thì càng nhanh kỹ năng C ++ của bạn sẽ được.
Từ quan điểm duy trì, tôi cũng nên đề cập rằng khi bạn sử dụng con trỏ, bạn phải kiểm tra tính hợp lệ của chúng và xử lý trường hợp khi chúng không hợp lệ, hoặc, giả sử chúng hợp lệ và chấp nhận sự thật rằng chương trình sẽ sụp đổ hoặc tệ hơn KHI giả định đó bị hỏng. Nói cách khác, lựa chọn của bạn với con trỏ là giới thiệu độ phức tạp của mã hoặc nỗ lực bảo trì nhiều hơn khi có lỗi xảy ra và bạn đang cố gắng theo dõi một lỗi thuộc về cả một loại lỗi mà con trỏ đưa ra, như hỏng bộ nhớ.
Vì vậy, nếu bạn kiểm soát tất cả các mã của mình, hãy tránh xa các con trỏ và thay vào đó sử dụng các tham chiếu, giữ chúng là const khi bạn có thể. Điều này sẽ buộc bạn phải suy nghĩ về thời gian sống của các đối tượng của bạn và cuối cùng sẽ giữ cho mã của bạn dễ hiểu hơn.
Chỉ cần nhớ sự khác biệt này: Một tham chiếu về cơ bản là một con trỏ hợp lệ. Một con trỏ không phải lúc nào cũng hợp lệ.
Vì vậy, tôi có nói rằng không thể tạo ra một tài liệu tham khảo không hợp lệ? Không. Hoàn toàn có thể, bởi vì C ++ cho phép bạn làm hầu hết mọi thứ. Việc làm vô tình chỉ khó hơn và bạn sẽ ngạc nhiên khi có nhiều lỗi vô ý :)