2014-09-09 23 views
5

Tôi biết câu hỏi này có vẻ rất cơ bản. Nhưng tôi không thể tìm thấy bất cứ nơi nào một ví dụ về một nhà xây dựng di chuyển với các con trỏ no.Di chuyển Constructor không có con trỏ

Tôi có một lớp chứa biến đối tượng vectơ. Không phải là một con trỏ đến một. Vì vậy, câu hỏi của tôi: Điều này có nghĩa rằng tôi không có nhu cầu trong một nhà xây dựng di chuyển? Hoặc là thực hiện của tôi sai và tôi nên sử dụng một con trỏ đến một vector và sau đó sử dụng một nhà xây dựng di chuyển?

Cảm ơn bạn

+2

Bạn vẫn nên có một hàm tạo di chuyển, vì 'std :: vector' có thể hưởng lợi từ việc di chuyển. Trình biên dịch tạo ra (di chuyển theo từng phần) phải đủ tốt. –

+0

Tôi tin rằng nó được gọi là * Sao chép Constructor *, chứ không phải * Di chuyển Constructor *. –

+1

@AlexFarber: Trình tạo bản sao mặc định là đủ tốt nếu không có con trỏ thành viên nào (như đã đề cập ở trên bởi T.C.). –

Trả lời

10

Nếu lớp học của bạn chứa các đối tượng di động (chẳng hạn như một vector), sau đó chỉ cần để cho các trình biên dịch tạo ra các hoạt động di chuyển ngầm. Họ sẽ làm điều đúng, di chuyển từng subobject.

Bạn sẽ chỉ cần viết của riêng mình nếu bạn đang đưa các con trỏ thô vào các đối tượng động hoặc các tài nguyên không được quản lý khác. Cách tiếp cận tốt nhất là có một đối tượng có thể sao chép/di chuyển chính xác (chẳng hạn như vùng chứa, con trỏ thông minh hoặc lớp RAII khác) để quản lý từng đối tượng này; sau đó một đối tượng phức tạp được xây dựng bằng cách soạn thảo những điều này sẽ ngầm có đúng ngữ nghĩa sao chép/di chuyển.

(Như đã nêu trong nhận xét: nếu lớp học của bạn tuyên bố hủy của riêng mình hoặc sao chép hoạt động, sau đó nó sẽ không nhận được hoạt động di chuyển tiềm ẩn, bạn sẽ cần phải xác định của riêng bạn.Nhưng nếu bạn làm theo những lời khuyên trên, sáng tác từ các loại được quản lý đúng cách không cần xử lý đặc biệt, thì bạn không cần phải khai báo bất kỳ điều nào trong số này.)

+0

Vì vậy, để cho trình biên dịch tạo ra nó, implicitley vẫn đủ hiệu quả? Hoặc tôi nên sử dụng con trỏ? – wjk2a1

+3

@ wjk2a1: Sử dụng phiên bản ngầm định có thể sẽ hiệu quả hơn việc đưa thêm một mức độ vô hướng, và chắc chắn đơn giản hơn và ít bị lỗi hơn. Nếu bạn thực sự cần phải lo lắng về chi phí của bản cập nhật con trỏ cá nhân, thì bạn sẽ cần phải tự mình đo lường chi phí của cả hai phương pháp tiếp cận. –

+0

rất hữu ích, Cảm ơn bạn! – wjk2a1

3

Di chuyển hàm tạo tuân thủ các nguyên tắc tương tự như các nhà xây dựng sao chép. Nó là bắt buộc khi lớp của bạn chứa các thành viên bằng con trỏ hoặc các trường dữ liệu mong manh khác (ổ cắm, kết nối db, v.v.), để tạo tự động có thể làm rối loạn bố trí bộ nhớ bằng cách xóa cùng một đối tượng hai lần. Vì vậy, nếu bạn không có bất kỳ trường con trỏ nào, bạn không phải viết hàm tạo di chuyển.

1

Hàm khởi tạo mặc định và di chuyển asignment được tạo bởi trình biên dịch sẽ gọi hàm khởi tạo di chuyển/sắp xếp cho từng thành viên của lớp.

Nếu lớp học của bạn chỉ có thành viên thô, "bộ đệm char *", bạn phải viết hoạt động di chuyển của riêng bạn.

Nếu lớp của bạn chỉ có "thành viên được quản lý", "vectơ", ví dụ, các hoạt động di chuyển mặc định cho lớp học của bạn sẽ được chấp thuận vì nó ủy nhiệm hoạt động cho từng thành viên.

Nếu lớp học của bạn đã trộn lẫn với "thành viên thô", vector và * int ví dụ "các thành viên quản lý", các hoạt động phong trào của bạn sẽ phải thực hiện di chuyển thủ công các nguồn tài nguyên thô và gọi hoạt động di chuyển cho các đối tượng quản lý:

class MyObject { 
public: 
    // ... 


    MyObject(MyObject&& other) : vector1(std::move(other.vector1)) { 
     // We use vector's move constructor^

     // and then move ourself the char* buffer 
     buffer1 = other.buffer1; 
     other.buffer1 = nullptr;   
    } 

    MyObject& operator=(MyObject&& other) { 
     // We use vector's move asignment operator 
     vector1= std::move(other.vector1); 

     // and then move ourself the char* buffer 
     std::swap(buffer1,other.buffer1); 
     return *this; 
    } 

    //... 
private: 
    vector<char> vector1; 
    char * buffer1; 
}; 

std :: di chuyển (other.vector1) là cần thiết vì bên trong chức năng khác.vector1 là một giá trị. Chúng ta phải nói với trình biên dịch, chúng ta sẽ không sử dụng giá trị vector1 sau trong mã chức năng để giá trị của nó có thể được di chuyển.

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