2010-04-26 37 views
15

thể trùng lặp:
Why would you ever want to allocate memory on the heap rather than the stack?C++ Con trỏ đối tượng vs Non Pointer Objects

Test2 *t2 = new Test2(); 
t2->test(); 

Test2 t3; 
t3.test(); 

Tại sao tôi muốn tạo ra một đối tượng con trỏ kiểu Test2? Tại sao không chỉ làm phiên bản con trỏ của Test2? Tại sao tôi muốn làm đối tượng con trỏ?

Tìm thấy câu trả lời ở đây:

+1

Nhiều bản sao, trước tiên là (từ câu trả lời của Firas Assaad) http://stackoverflow.com/questions/1549945/why-would-you-ever-want-to-allocate-memory-on-the-heap -rather-than-the-stack –

+1

Tôi nhận ra điều đó ngay bây giờ. Tuy nhiên đặt câu hỏi là phần khó. Bây giờ tôi nghĩ rằng tôi nhận được nó ...: D –

Trả lời

19

Những lý do để sử dụng lưu trữ năng động bao gồm (nhưng có lẽ không giới hạn)

  1. kiểm soát bằng tay của các đối tượng suốt đời - đối tượng sẽ sống cho đến khi bạn dứt khoát tiêu diệt nó
  2. Tạo như nhiều đối tượng khi cần thiết, khi số lượng các đối tượng cuối cùng chỉ được biết ở thời gian chạy (như số lượng các nút trong một cây hoặc số phần tử trong một mảng).
  3. Kiểm soát thời gian chạy của loại đối tượng (như loại đối tượng đa hình thực tế).

Khi không có sự khác biệt, bạn nên tạo đối tượng bằng cách sử dụng phương thức t3. Không sử dụng bộ nhớ động trừ khi bạn phải. Nhưng đôi khi bạn thực sự phải (xem những lý do trên).

7

Nếu bạn cần một đối tượng để sống lâu hơn phạm vi được tạo, thì một trong các giải pháp sẽ là tạo ra nó trên Heap. Trong trường hợp đó bạn sẽ cần một con trỏ. Có nhiều lý do khác nữa, đây là lý do phổ biến nhất.

Một lý do khác để sử dụng con trỏ là cho tham số "ngoài". Cấp cho bạn có thể sử dụng tài liệu tham khảo, nhưng nhiều người thích sử dụng con trỏ vì nó làm giảm sự sửa đổi của tham số tại trang cuộc gọi. foo(var); vs foo(&var);

Ngoài ra, con trỏ có thể được sử dụng để truyền hoặc trả về một đối tượng có thể tồn tại hoặc không tồn tại. Ví dụ: T *foo(); // returns a pointer to an object or NULL if none exists.

Danh sách tiếp tục và thực sự.

+0

Bạn có thể liệt kê một số lý do khác không? –

+1

Không đúng sự thật. Đối tượng được khai báo là 'static Test2 t3;' trong phạm vi cục bộ sẽ vượt quá phạm vi được tạo. Tuy nhiên, nó không được tạo trên heap. – AnT

+0

@AndreT: điểm tốt, tôi sẽ sửa lại câu trả lời của mình. –

3

Bất kỳ loại cấu trúc dữ liệu động nào (danh sách, cây nhị phân, ngăn xếp, v.v ...) đều phải sử dụng con trỏ đến đối tượng.

1

Triển khai phổ biến (nhưng không bắt buộc) là các biến cục bộ được cấp phát trên ngăn xếp. Ngăn xếp là hữu hạn và có thể có một đối tượng quá lớn để phân bổ trên ngăn xếp.

4

Nếu bạn có một đối tượng rất lớn (ví dụ một với bộ đệm rất lớn làm thành viên), bạn có thể không muốn phân bổ nó trên ngăn xếp, vì không gian ngăn xếp bị giới hạn, trong trường hợp đó bạn phân bổ trên heap với toán tử Mới.

+0

Cảm ơn bạn; Tôi là một lập trình viên Java và C++ nhưng các lớp của tôi không bao giờ đi qua đống/heap ... –

2

Sự khác biệt chính là nơi nó sống trong bộ nhớ. Phiên bản "con trỏ không" sống trên stack, có nghĩa là nó sẽ không hợp lệ khi hàm trả về, trong khi "phiên bản con trỏ" sống trên heap, có nghĩa là nó sẽ còn sống và tốt cho đến khi ai đó gọi delete trên đó. Nói chung nó được coi là thực hành tốt nhất để đặt các đối tượng trên stack bất cứ khi nào có thể, và chỉ trên đống khi cần thiết. Một ví dụ điển hình cần các đối tượng trên heap sẽ là một cái gì đó như thế này

Obj* f() 
{ 
    return new Obj(); 
} 

các new Obj() tạo ra một đối tượng Obj trên heap và trả về một con trỏ đến nó, mà sau đó được trả về từ hàm.

này, ví dụ, sẽ KHÔNG làm việc

Obj* f() 
{ 
    Obj o1; 
    return &o1; //BAD!! 
} 

Kể từ khi giá trị con trỏ bộ nhớ tham khảo &o1 trên stack, và f() sẽ bị xóa ra khỏi stack vào thời điểm đó, ai mà biết được điều gì sẽ xảy ra. Chắc chắn không có gì tốt.

Các vấn đề liên quan