2013-08-10 30 views
10

tôi đã tìm kiếm trên Internet và tìm thấy 3 cách xác định một constructor di chuyển:Làm thế nào để xác định đúng một hàm tạo di chuyển?

  1. Dựa vào trình biên dịch:

    T(T&& other) = default; 
    
  2. dereference this con trỏ:

    T(T&& other) { 
        *this = std::move(other); 
    } 
    
  3. Rõ ràng phân công lại tất cả thành viên:

    T(T&& other) { 
        T.a = other.a; 
        T.b = other.b; 
        //... 
    } 
    

Cách nào là đúng? (Và là một trong những thứ hai thậm chí có đúng không?)

+3

Thứ hai là không chính xác (bạn thường không thể tham chiếu đến một đối tượng không tồn tại), thứ ba là ngớ ngẩn. –

+0

@KerrekSB Tôi tìm thấy trang web thứ hai từ trang web MSDN: http://msdn.microsoft.com/en-us/library/dd293665.aspx có lẽ MSVC hỗ trợ nó .. không chắc chắn về GCC – texasbruce

+0

Tôi đã tìm thấy trang thứ ba từ trang đó quá ... – texasbruce

Trả lời

15

Cách chung thích hợp là để di chuyển-xây dựng từng thành viên, nhưng đó là những gì các phiên bản defauted làm anyway:

T(T && rhs) 
: a(std::move(rhs.a)) 
, b(std::move(rhs.b)) 
{ } 

Như một quy luật khó khăn, bạn nên sử dụng định nghĩa mặc định nếu điều này là tất cả các bạn cần, và bạn nên viết một cựu ­ PLI ­ cit di chuyển constructor nếu bạn đang làm cái gì mà cựu ­ PLI ­ citly cụ di chuyển ngữ nghĩa, chẳng hạn như một người quản lý tài nguyên độc đáo sở hữu:

URM(URM && rhs) 
: resource(rhs.resource) 
{ 
    rhs.resource = nullptr; 
} 

Chỉ báo cho dù điều này là thích hợp có lẽ là lớp học của bạn có một người dùng xác định de ­ struc ­ tor. Trong ví dụ, destructor sẽ giải phóng tài nguyên được quản lý và điều này phải xảy ra chỉ một lần, vì vậy đối tượng di chuyển từ phải được sửa đổi.


Đây là không liên quan, nhưng kể từ khi bạn đang nhắc đến toán tử gán, sau đây là phổ biến swap-and-assign/hoán đổi thành ngữ:

void swap(URM & rhs) noexcept  // assume members are noexcept-swappable! 
{ 
    using std::swap; 
    swap(resource, rhs.resource); 
    // ... 
} 

URM & operator=(URM rhs) noexcept // pass by value 
{ 
    rhs.swap(*this); 
    return *this; 
} 

Vẻ đẹp của phương pháp này là bạn chỉ cần một phiên bản duy nhất của toán tử gán hoạt động cho tạm thời và không đồng thời, sử dụng di chuyển xây dựng khi thích hợp và miễn là tất cả các thành viên của bạn được thiết kế tốt, bạn cũng chỉ cần một hàm swap. Trên hết, nếu chức năng hoán đổi không ném (mà một lớp được thiết kế tốt nên cho phép), thì toán tử gán của bạn không ném, vì tất cả các ngoại lệ có thể đã xảy ra tại trang gọi.

+0

Thực sự là cần thiết cuối cùng nếu, ví dụ, 'tài nguyên' là một' std :: unique_ptr'? –

+3

@JoachimPileborg: Không. Ví dụ có thể là * triển khai * của 'unique_ptr'. –

+0

Làm thế nào về mặc định? Tôi có thể sử dụng nó một cách an toàn không? – texasbruce

1
T(T&& other) 
: data(0) // initialize members 
{ 
    swap(other); // where the class has a member function swap or std::swap(this->data, other.data) 
} 
Các vấn đề liên quan