Để tạo đối tượng B
ở trạng thái hợp lệ, bạn không phải làm gì thêm nữa. Bạn thậm chí không phải khai báo và triển khai hàm tạo và hàm hủy cho B
. std::vector<std::shared_ptr<A>>
là thành viên của B
sẽ được khởi tạo mặc định trong hàm tạo của B
có nghĩa là nó sẽ không có bất kỳ phần tử nào trong vùng chứa. Nó cũng sẽ bị xóa một cách chính xác trong ~B
nhờ vào số std::vector
và std::shared_ptr
trình phá hủy.
Mặt khác, nếu bạn muốn khởi tạo bằng cách nào đó (ví dụ:3 giá trị), bạn có thể sử dụng hàm tạo 's std::initializer_list
trong danh sách khởi tạo hàm khởi tạo của B
. Ví dụ:
class B
{
public:
B(): _innerArray{ std::make_shared<A>(),
std::make_shared<A>(),
std::make_shared<A>() } {}
~B() {}
private:
std::vector<std::shared_ptr<A>> _innerArray;
};
Hãy nhớ rằng std::make_shared
sử dụng chuyển tiếp hoàn hảo để bạn vượt qua A
đối số của constructor như các đối số chức năng và không phải là đối tượng lớp riêng của mình.
Trả lời các thắc mắc của bạn về thiết kế Tôi muốn khuyến khích bạn trước tiên nghĩ về quyền sở hữu độc quyền của các thành viên trong một véc tơ trước khi bạn quyết định chia sẻ chúng.
class B
{
public:
B();
~B();
private:
std::vector<std::unique_ptr<A>> _innerArray;
};
Thực hiện ở trên hiệu quả hơn trên nhiều cơ sở. Trước hết nó làm cho thiết kế của bạn rõ ràng hơn về ai chịu trách nhiệm về tuổi thọ của A
s. Tiếp theo std::unique_ptr
nhanh hơn vì nó không yêu cầu tính tham chiếu an toàn chỉ. Và cuối cùng nhưng không kém phần chi phí bộ nhớ bổ sung (so với con trỏ C thông thường) trong khi std::shared_ptr
có thể mất hàng chục byte (24-48) để lưu trữ dữ liệu trạng thái được chia sẻ rất hiệu quả khi bạn hoạt động trên các lớp nhỏ. Đó là lý do tại sao tôi luôn sử dụng std::unique_ptr
làm con trỏ thông minh đầu tiên của mình và tôi chỉ dự phòng số std::shared_ptr
khi thực sự cần thiết.
EDIT:
Answering chỉnh sửa của bạn tôi sẽ tạo ra 3 container của các tầng lớp A
, B
, C
. Tùy thuộc vào thực tế nếu bạn cần họ để được đa hình hay không tôi sẽ lưu trữ một trong hai giá trị như thế (loại không đa hình):
std::deque<A> as;
std::deque<B> bs;
std::deque<C> cs;
hoặc (loại đa hình):
std::vector<std::unique_ptr<A>> as;
std::vector<std::unique_ptr<B>> bs;
std::vector<std::unique_ptr<C>> cs;
theo thứ tự (as
phải dài hơn bs
và bs
phải dài hơn cs
). Sau đó, tôi chỉ có std::vector<A*>
bên trong lớp B
và std::vector<B*>
bên trong C
lớp mà không cần sử dụng con trỏ thông minh nào.
Tôi hy vọng điều đó sẽ hữu ích.
EDIT:
Changed std::vector
để std::deque
trong trường hợp đầu tiên cho phép tài liệu tham khảo/con trỏ đến các yếu tố chứa tồn container mở rộng với push_back()
. Tuy nhiên, chúng sẽ không tồn tại các yếu tố tẩy xoá, phân loại hoặc các thứ khác.
Kiểm tra tính chất: bạn có cần con trỏ ở đây không? Và nếu vậy, nó có nên là một con trỏ được chia sẻ không? –
Lớp B được cho là có quyền truy cập nhưng không sở hữu một số đối tượng được lưu trữ ở nơi khác. Tôi không thấy sử dụng unique_ptr thay vì shared_ptr làm cho bất kỳ ý nghĩa ở đây, nhưng tôi là một noob để con trỏ thông minh. –
@Pavel Bạn nói đúng: kịch bản của bạn ngăn cản việc sử dụng 'unique_ptr', và nó yêu cầu sử dụng con trỏ. Tuy nhiên, nếu 'B' không được coi là sở hữu, tôi thậm chí còn xem xét sử dụng con trỏ thô thay vì con trỏ được chia sẻ. Xét cho cùng, khái niệm sau biểu thị * quyền sở hữu được chia sẻ * (nhưng có thể đó là những gì bạn yêu cầu sau khi tất cả). –