Có nên dùng con trỏ khi đã học

Chào các pro ạ, mình vừa học xong con trỏ, thế sau này mỗi khi viết chương trình thì sử dụng con trỏ hả cho tiết kiệm bộ nhớ hả, nên hay không nên sử dụng con trỏ nhiều?.

Dùng con trỏ chả bao giờ là tiết kiệm bộ nhớ cả
-> học chưa xong -> học lại.

3 Likes

Chắc là bạn mới học khởi tạo con trỏ dưới dạng mảng nên nghĩ là con trỏ tiết kiệm bộ nhớ :smile:
Thực ra cũng có ý đúng, cơ mà con trỏ chủ yếu dùng để linh động hoá các biến thôi. Tuy nhiên nó lại tiềm ẩn nguy cơ trỏ lung tung và hao tốn bộ nhớ nếu bạn không nắm chắc các cơ chế cấp phát và khởi tạo nó. Cái gì biết thì dùng.

Nếu bạn định khai báo mảng thì nên dùng con trỏ, nhưng nhớ giải phóng bộ nhớ cho nó khi không dùng nữa.

1 Like

Hỏi ngu 1 chút, bác @Duong_Act và anh @noz1995 giải thích giúp em với, không học con trỏ có làm sao không ạ? Lúc nào phải dùng con trỏ ạ?

Mình nghĩ bạn phải biết thừa chứ, chắc lại hỏi hộ người khác :smile:
Mình không biết rõ lắm. Tại mình không học con trỏ, bên C# chỉ dùng con trỏ trong unsafe code, mà mình chỉ học lập trình cho vui.

Không hẳn ạ. Mấy năm nay em code không cần con trỏ cũng chẳng làm sao (chắc tại chưa đến lúc gặp), mà em thấy cơ bản C/C++ nhiều người học con trỏ mà em chả biết nó là cái gì.

Không nhầm thì các dữ liệu lớn nên cấp trên heap. Stack có kích thước nhỏ tuy nhiên mỗi cái có lợi hại riêng tùy kiến trúc tối ưu mà xử lý.

1 Like

Nếu chỉ giải bài tập hay học trên lớp thì có lẽ không bao giờ cần dùng con trỏ, vì bạn có thể sử dụng return của hàm,…

Tuy nhiên khi làm việc với dữ liệu lớn như cấp phát vùng nhớ trong game (1 object nhân vật), nó bao gồm rất nhiều dữ liệu, nếu mỗi lần render mà copy/delete cả object thì bạn thử tưởng tượng xem nó sẽ thế nào. 1 game chạy trung bình 30-60fps, 1 object có khoảng 15VAO, 1 VAO có khoảng vài trăm VBO, vậy thì bao nhiêu s mới render xong một object/1 frame? Tốn bao nhiêu bộ nhớ để render?

Đối với con trỏ, việc duy nhất nó làm là copy địa chỉ, dung lượng 1 con trỏ rất nhỏ, không quan trọng kiểu dữ liệu.

4 Likes

Bạn không nói dùng ngôn ngữ nào, vậy nên để tư vấn cũng rất chung chung.

Với C/C++(thuần không boost) <=03, sử dụng raw pointer, raw pointer rất nhẹ, linh hoạt, tuy nhiên nhược điểm là phải xoá thủ công(cũng có thể coi là ưu điểm, vì khi nào muốn xoá sẽ ra lệnh cho os xoá, giả sử game đang trong time rảnh 1-2s), nhưng nếu không quản lí tốt nó, có thể gây tổn hại cho os.

Từ C++11(boost có sớm hơn, stl lấy từ boost), bạn có thể dùng smart pointer, nó không khác gì những biến thông thường, tự xoá khi ra khỏi scope, tuy nhiên nếu có 1 con trỏ khác đang giữ thì địa chỉ của nó sẽ không bị xoá, 2 smart_ptr chính hay dùng và thường khó quyết định là shared_ptr và unique_ptr, những lúc không biết nên dùng thằng nào thì cứ shared_ptr.

Hãy dùng nó khi bạn hiểu về nó, hiểu mình đang làm gì. Còn bạn nói học xong rồi mà không biết cách dùng thì mình cũng hơi ngại

3 Likes

Có trường hợp nào mà phải dùng con trỏ, nếu né con trỏ ra thì phải code vô cùng phức tạp không bác?

Java, C# mỗi object tạo bằng new ra rồi gán cho 1 biến đều là con trỏ cả rồi, bạn xài bình thường có thấy gì phức tạp đâu??

3 Likes

Mình cũng chưa gặp truờng hợp nào như vậy, vì lúc nào cũng sẽ có cách giải quyết, khi sử dụng con trỏ sẽ tiện hơn thôi.
Khó nhất chắc là lúc code socket udp/ip, nếu không dùng con trỏ để điều khiển queue mà từng client gửi lên, hay làm việc với client hiện tại thì sẽ hơi khó.

1 Like

Vậy là bạn vẫn chưa hiểu :slight_smile: con trỏ không chỉ trỏ đến, mà trong nhiều trường hợp còn quản lí vùng nhớ nữa (theo cả góc nhìn của OS và LTV), bạn có thể thấy nó có rất nhiều công dụng.

Để swap các dòng trong ma trận (kiểu mảng con trỏ) thay vì deep swap ta swap hai con trỏ tương ứng O(1).

Cần phải thấy rằng con trỏ có thể đại diện cho cả một vùng nhớ liên tục, chứ không đơn thuần là chỉ trỏ.

1 Like

Có, nếu bạn làm những ứng dụng với dữ liệu lớn như file ảnh, phim… thì nếu không dùng pointer thì mỗi file ảnh của bạn sẽ có 1 bản sao trên ram, nếu bạn tạo 1 vòng lặp duyệt danh sách ảnh thì cứ mỗi lần như thế sẽ sao chép file ảnh đó lên => chậm, tốn ram. Nhờ pointer mà bạn chỉ cần load file ảnh lên ram 1 lần, sao đó nhớ địa chỉ của nó, khi cần đọc chỉ cần cho pointer trỏ đến và dùng.
Sâu hơn nữa nếu bạn hiểu về cách mà OS cấp phát và đọc dữ liệu trên RAM thì bạn sẽ thấy pointer cực quan trọng. Nói một cách đơn giản thì OS sẽ có 2 trạng thái, kernel mode và user mode, khi việc cấp phát xãy ra thì OS sẽ chuyển từ user mode sang kernel mode và khi cấp xong sẽ quay trở lại, việc chuyển đổi như vậy có thể tốn hàng nghìn clock của CPU. Do đó các hệ thống lớn họ sẽ viết hẳn 1 trình cấp phát riêng, đơn giản nhất là mô phỏng vùng nhớ stack của OS, khi app bắt đầu chạy thì họ chỉ cần 1 lần chuyển sang kernel mode và dùng malloc() cấp phát vài trăm mb cho tới cả Gb dữ liệu, sau đó cho pointer trỏ tới, khi một biến nào đó cần dữ liệu thì thay vì OS sẽ cấp thì giờ đây bạn sẽ cấp từ vùng nhớ vài trăm mb đó của mình. Lưu ý việc này chỉ làm khi mà hệ thống của bạn có thể dùng lên tới cả Gb RAM.

2 Likes

Hi Phương Trọng Lê.
Việc tự quản lý cấp phát bộ nhớ không phụ thuộc vào kích thước bộ nhớ dùng. Thường dùng cho hệ thống cấp phát nhiều và liên tục và đi kèm với giải phóng liên tục.

Hi bạn, tùy vào quan điểm của mỗi người, đối với bài viết của bạn thì nó chỉ đơn giản đề cập về việc cấp phát và cách quản lý các cấp phát đó, trong khi đó memory management rất rộng và liên quan tới việc quản lý tham chiếu, thu hồi tự động, chống phân mảnh và tùy vào đặc tính của hệ thống nó sẽ có nhiều dạng khác nhau, ở đây mình là người đang làm việc với tầng game engine và các dữ liệu thường rất lớn và được thêm vào ở run-time thì đối với mình việc cấp phát sẵn như thế sẽ rất có lợi để lưu dữ liệu lớn vì tránh cho OS chuyển đổi các mode khi cấp phát heap xãy ra, và cũng để minh áp dụng các kỹ thuật phân cấp bộ nhớ thành các vùng riêng biệt tùy vào tần số sử dụng để tránh xãy ra cache miss.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?