2013-02-24 48 views
7

Đến từ một nền Java, tôi vẫn còn hơi bối rối về việc cấp phát bộ nhớ trong C++. Tôi chắc chắn hai tuyên bố đầu tiên là chính xác:C++ Phân bổ bộ nhớ trên heap và ngăn xếp?

void method() { 
    Foo foo; // allocates foo on the stack, and the memory is freed 
       // when the method exits 
} 

void method2() { 
    Foo *foo = new Foo(); // allocates foo on the heap 
    delete foo;    // frees the memory used by foo 
} 

Nhưng còn về điều gì đó như thế này?

void method3() { 
    Foo foo = *new Foo(); // allocates foo on the heap, and then copies it to the stack? 
          // when the method exits, the stack memory is freed, but the heap memory isn't? 
} 

Giả sử tôi đã thêm foo vào mảng toàn cầu bên trong method3(). Nếu tôi cố gắng truy cập một trong số các thành viên dữ liệu của foo sau khi thoát khỏi phương pháp, điều đó có hiệu quả không? Và có phải method3() dễ bị rò rỉ bộ nhớ không?

Xin cảm ơn trước.

+1

'Foo foo();' thực sự không phân bổ bất kỳ thứ gì. Nó khai báo một hàm. – chris

Trả lời

8
Foo foo(); 

Khai báo chức năng theo tên foo trả về đối tượng Foo và không nhận bất kỳ đối số nào. Nó được gọi là phân tích cú pháp gây tranh cãi nhất trong C++. Bạn có thể có nghĩa là:

Foo foo; 

Tạo một đối tượng địa phương/tự động lưu trữ. Đối tượng được tự động deallocated khi phạm vi { }, trong đó nó được khai báo kết thúc.


Foo *foo = new Foo(); // allocates foo on the heap 
delete foo; 

này là sự thật, các đối tượng trên freestore trỏ bởi foo được deallocated khi bạn gọi delete. Không có rò rỉ bộ nhớ.


Foo foo = *new Foo(); 

Phân bổ một đối tượng Foo trên freestore và sau đó một bản sao của đối tượng đó được sử dụng để khởi foo. Vì bạn không có con trỏ tới đối tượng được phân bổ freestore, nó gây ra rò rỉ bộ nhớ. Lưu ý rằng nếu destructor của Foo có một số mã gây ra tác dụng phụ thì nó không chỉ đơn thuần là rò rỉ bộ nhớ mà còn là hành vi không xác định.

+0

Tôi có nghĩa là 'Foo foo()' để gọi hàm tạo không đối số cho lớp 'Foo'. Nhưng bạn nói đúng, tôi sẽ thay đổi nó trong câu hỏi để tránh nhầm lẫn. – nebulabrot

+1

@nebulabrot: 'Foo foo;' làm điều đó, không phải 'Foo foo();' –

+0

Tại sao hành vi không xác định nếu tác dụng phụ có mặt trong Foo destructor? Tôi có thể nghĩ ra một vài ví dụ với phức tạp 'Foo', nơi nó sẽ hoạt động tốt, ngay cả khi không bị rò rỉ bộ nhớ! – CygnusX1

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