2013-07-24 34 views
8

Từ cplusplus.com:C++ copy constructor với các thành viên shared_ptr

Hiếm khi bạn sẽ đi qua một lớp học mà không chứa con trỏ nguyên chưa constructor sao chép mặc định là chưa đủ. Ví dụ về số này là khi bạn có đối tượng được tính tham chiếu. boost :: shared_ptr <> là ví dụ.

Ai đó có thể giải thích về điều này? Nếu chúng tôi có một lớp học có chứa một boost::shared_ptr, sẽ không có được bản sao xây dựng khi lớp được sao chép xây dựng - và do đó sẽ không phải là nhà xây dựng shared_ptr làm điều đúng và tăng số lượng tài liệu tham khảo? Các mã sau đây, ví dụ, bản sao Inner đúng - tại sao không làm việc này cho shared_ptr:

#include <iostream> 
using namespace std; 

class Inner 
{ 
public: 
Inner() { cout << "inner default constructed" << endl;} 
Inner(const Inner& other) { cout << "inner properly copied" << endl;} 
}; 

class Outer 
{ 
Inner i; 
}; 

int main() { Outer o; Outer p(o); return 0;} 
+8

Có thể bạn đã không bị vấp phải bởi các âm bản kép bị thiếu mà không có trong tuyên bố đó? –

+0

Quên nó đi, nó chỉ là bollocks. Giả sử nó không đề cập đến shared_ptr. Tôi đoán đây là một lý do khác khiến cplusplus.com bị thu hồi. –

+0

Vì vậy, để đặt câu hỏi hay hơn thì. Khi mọi người nói "hàm tạo bản sao mặc định thực hiện bản sao nông", điều đó có nghĩa là "nó gọi các nhà xây dựng sao chép của tất cả các thành viên lần lượt" hoặc "nó chỉ thực hiện memcpy() trên cá thể lớp" –

Trả lời

12

Trình tạo bản sao mặc định sẽ sử dụng hàm tạo bản sao cho mỗi biến thành viên hoặc bản sao bit-bit cho các loại được cài sẵn.

Nếu bạn đang sử dụng một con trỏ được chia sẻ của một loại nào đó, hàm tạo bản sao sẽ tăng số lượng chia sẻ và cả đối tượng ban đầu lẫn đối tượng mới sẽ trỏ đến cùng một đối tượng.

Trong một số trường hợp, đây là những gì bạn muốn; sao chép con trỏ và quản lý chính xác số tham chiếu sao cho tài nguyên có thể được giải phóng khi nó không còn được sử dụng nữa.

Ngữ cảnh của bài viết được trích dẫn là đang sao chép toàn bộ đối tượng. Trong trường hợp này, mỗi đối tượng sẽ được yêu cầu có bản sao riêng của các subobject của nó, và không chia sẻ các subobject với các trường hợp khác. Trong trường hợp này, shared_ptr có lẽ là sự lựa chọn sai, và chắc chắn sẽ không sao chép sâu các subobject.

Đoạn văn được viết sai, nhưng tôi chắc chắn nó đang nói về bản sao sâu nhưng nói rằng shared_ptr sẽ không cung cấp bản sao sâu đó. Đó là sự thật, bởi vì đó không phải là những gì nó được thiết kế cho.

1

Tôi nghĩ rằng nó có nghĩa là lớp mới sẽ đề cập đến tài nguyên lớp cũ, nơi bạn có thể mong đợi một bản sao đến? được tạo thành từ tài nguyên cũ cho lớp mới, như sẽ xảy ra nếu nó là thành viên đầy đủ của lớp. Hoặc là chấp nhận được - nó phụ thuộc vào những gì bạn đang làm.

Ví dụ: nếu bạn sao chép một chú chó và một con chó có xương, con chó mới có lấy được xương của chính nó không, hoặc nó có chia sẻ xương gốc không?

+0

Đó là những gì đoạn trước trong bài viết được liên kết mô tả; nếu đối tượng chứa một con trỏ thô đến một tài nguyên mà nó quản lý (thường là một ý tưởng rất tồi) thì bạn sẽ cần một trình tạo bản sao để xử lý điều đó. Đoạn trích dẫn đơn giản là vô nghĩa. –

+0

Nếu bạn muốn đối tượng được sao chép có bản sao của tài nguyên gốc và không chia sẻ nó, bạn sẽ cần một hàm tạo bản sao khi sử dụng shared_ptr –

+0

Tôi hiểu. Có, có lẽ tác giả đang cố gắng nói rằng bạn sẽ cần một nhà xây dựng bản sao nếu bạn sử dụng một con trỏ chia sẻ khi bạn không muốn các ngữ nghĩa được chia sẻ của nó. Đó là một điều khá lạ lùng để làm. –

5

Ai đó có thể giải thích về điều này?

Không thực sự; nó là vô nghĩa.

Nếu chúng ta có một lớp có chứa một boost::shared_ptr, sẽ không phải là nhận được bản sao xây dựng khi lớp được copy xây dựng - và do đó sẽ không phải là constructor shared_ptr làm điều đúng và tăng số lượng tài liệu tham khảo?

Đúng vậy. shared_ptr được thiết kế phù hợp với ngữ nghĩa sao chép hợp lệ, vì vậy không cần phải xử lý nó một cách đặc biệt khi sao chép một đối tượng lớp chứa một.

Có thể, tác giả có nghĩa là nếu bạn muốn sao chép, thay vì chia sẻ, đối tượng được chia sẻ, thì bạn sẽ cần một trình tạo bản sao để tạo một đối tượng mới. Tuy nhiên, nó khá lạ khi sử dụng shared_ptr nếu bạn không muốn chia sẻ quyền sở hữu.