2010-08-12 30 views
6

Cách nào là đúng cách để cấp phát bộ nhớ qua new trong hàm dựng C++. Cách thứ nhất trong danh sách đối số:Cách đúng để cấp phát bộ nhớ trong hàm dựng C++ là gì?

class Boda { 
    int *memory; 
    public: 
     Boda(int length) : memory(new int [length]) {} 
     ~Boda() { delete [] memory; } 
}; 

hoặc trong cơ thể của constructor:

class Boda { 
    int *memory; 
    public: 
     Boda(int length) { 
      memory = new int [length]; 
     } 
     ~Boda() { delete [] memory; } 
}; 

Cảm ơn, Boda Cydo.

+6

Tôi biết đây chỉ là mã ví dụ, nhưng khi được viết là lớp có vấn đề quản lý bộ nhớ nghiêm trọng (ctor sao chép mặc định sẽ cho phép bộ nhớ được deallocated nhiều lần). sử dụng RAII, sử dụng con trỏ thông minh hoặc thùng chứa. với RAII thích hợp, bạn có thể thấy bạn không cần phải tự xóa mình ở tất cả –

+8

@jk: Thứ hai, tôi thích 'std :: vector '. – fredoverflow

Trả lời

3

Tôi nghĩ cách đơn giản nhất để thực hiện việc này là sử dụng boost scoped array và để mã thư viện được kiểm tra tốt của người khác xử lý tất cả cho bạn.

Vì vậy:

class Boda { 
    boost::scoped_array<int> memory; 
    public: 
     Boda(int length) : memory(new int [length]) {} 
     ~Boda() {} 
}; 

Hơn nữa, scoped mảng không thể sao chép - vì vậy bạn tránh được những bản sao constructor vấn đề deallocation khó chịu đề cập trong câu trả lời khác.

+0

Thực ra, bạn nên sử dụng 'boost :: scoped_array'. –

+0

Cảm ơn. Chỉ cần phát hiện ra nó là một mảng phân bổ. Dạy tôi đọc câu hỏi đúng cách. –

+1

'xóa' là một mùi mã: nó chỉ nên xuất hiện trong các lớp quản lý tài nguyên chuyên dụng ... và chúng thường được mã hóa đúng trong các thư viện có sẵn (ví dụ: STL/Boost). –

-1

Nếu bạn muốn bắt lỗi phân bổ bộ nhớ (mà bạn có thể nên) thì bạn sẽ phải thực hiện cuộc gọi đến mới trong phần thân của hàm tạo.

+12

Không đúng sự thật. (Và trong cả hai trường hợp. Nếu phân bổ bộ nhớ không thành công, hàm khởi tạo này không thể làm gì về nó và vì vậy * không * bắt ngoại lệ. Và bạn có thể sử dụng khối try để lấy toàn bộ khối trong khối try-catch .) – GManNickG

1

Tôi có thể nói cả hai đều tương đương với hiệu quả mà chúng tạo ra và cả hai đều là "đúng cách". Tôi thích danh sách khởi tạo nhưng tôi sẽ đi với biến thể thứ hai chỉ để có thể kiểm tra đối số độ dài không hợp lệ trước khi cố gắng cấp phát bộ nhớ.

+1

Chúng tương đương với các loại đơn giản, nhưng nói chung thì không. Sử dụng danh sách initialiser sẽ xây dựng đối tượng từ các đối số; sử dụng phần thân của hàm tạo sẽ mặc định xây dựng đối tượng và sau đó gán lại nó. Điều này có thể kém hiệu quả hơn và sẽ chỉ hoạt động nếu đối tượng có cấu hình mặc định và có thể gán được. –

2

Bạn nên sử dụng các lớp quản lý tài nguyên sẽ xử lý các lớp đó cho bạn. Khác, bạn gặp phải một số vấn đề nghiêm trọng với sự an toàn ngoại lệ, ngoài việc không cần sao chép logic hiện có và bảo trì các toán tử gán/sao chép.

0

memory biến thành viên là một con trỏ, nếu bạn phân bổ nó trong danh sách khởi và nó không thành công, lớp học của bạn không được khởi tạo và bạn không cần phải giải phóng nó sau này (nhờ mẫu thiết kế RAII được sử dụng bởi C++ để khởi tạo lớp). Nếu bạn cấp phát bộ nhớ của nó bên trong phần thân của hàm tạo, hành vi tương tự sẽ xảy ra.

Nhưng nếu bạn muốn xử lý điều gì đó, hãy phân bổ bộ nhớ của nó trong phần thân của hàm tạo. Kiểm tra một cái gì đó hoặc thử/bắt nó hoặc in một số thông điệp hữu ích, nhưng ít nhất, bạn phải ném một ngoại lệ, bởi vì khởi tạo lớp của bạn bị hỏng.

Tôi nghĩ rằng phân bổ memory trong phần thân của hàm tạo dễ đọc hơn so với phương thức khác.

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