2012-01-14 29 views
10

Trừ khi tôi sai, nó có vẻ như là một trong hai công trình tốt - có một lý do thực hành tốt nhất để thích một trong những khác?Tôi có nên sử dụng std :: move hoặc std :: forward trong các nhà khai thác di chuyển/chuyển nhượng?

Ví dụ:

struct A 
{ 
    A(){} 
    A(const A&){ std::cout << "A(const A&)\n"; } 
    A(A&&){ std::cout << "A(A&&)\n"; } 
}; 

struct B 
{ 
    B(){} 
    B(const B& right) : x(right.x){ std::cout << "B(const B&)\n"; } 
    B(B&& right) : x(std::forward<A>(right.x)){ std::cout << "B(B&&)\n"; } 

    A x; 
}; 

struct C 
{ 
    C(){} 
    C(const C& right) : x(right.x){ std::cout << "C(const C&)\n"; } 
    C(C&& right) : x(std::move(right.x)){ std::cout << "C(C&&)\n"; } 

    A x; 
}; 

struct D 
{ 
    D(){} 
    D(const D& right) : x(right.x){ std::cout << "D(const D&)\n"; } 
    D(D&& right) : x(right.x){ std::cout << "D(D&&)\n"; } 

    A x; 
}; 

int main() 
{ 
    std::cout << "--- B Test ---\n"; 
    B b1; 
    B b2(std::move(b1)); 
    std::cout << "--- C Test ---\n"; 
    C c1; 
    C c2(std::move(c1)); 
    std::cout << "--- D Test ---\n"; 
    D d1; 
    D d2(std::move(d1)); 
} 

Output:

--- B Test --- 
A(A&&) 
B(B&&) 
--- C Test --- 
A(A&&) 
C(C&&) 
--- D Test --- 
A(const A&) 
D(D&&) 

Trả lời

14

Câu hỏi là: Có phải những người thực sự di chuyển hành constructor/chuyển nhượng vì lớp học? Hay chúng chỉ trông như thế từ góc mắt của bạn?

struct X{ 
    X(X&&); // move ctor #1 

    template<class T> 
    X(T&&); // perfect forwarding ctor #2 

    X& operator=(X&&); // move assignment operator #3 

    template<class T> 
    X& operator=(T&&); // perfect forwarding ass. operator #4 
}; 

Trong một thực di chuyển ctor (# 1) và di chuyển toán tử gán (# 3), bạn sẽ không bao giờ sử dụng std::forward, vì, như bạn đánh giá một cách chính xác, bạn sẽ luôn luôn di chuyển.

Lưu ý rằng std::forward không bao giờ có ý nghĩa nếu không có mẫu chuyển tiếp hoàn hảo (T&&). Đó chính xác là trường hợp cho # 2 và # 4. Ở đây, bạn sẽ không bao giờ sử dụng std::move, vì bạn không biết nếu bạn thực sự có một rvalue (A-OK) hoặc một lvalue (không quá nhiều).

Xem this answer of mine để được giải thích về cách std::forward thực sự hoạt động.

+0

Bạn nói đúng, tôi đã nhìn vào ctor sai. Tôi đã thêm một số mã ví dụ cho câu hỏi. – David

+0

@Dave: Việc bạn sử dụng 'std :: forward' là sai, vì' A' không phải là tham số mẫu được suy luận. Nó chỉ xảy ra là nó phù hợp với phiên bản "cast to rvalue" của 'std :: forward'. – Xeo

+0

Tôi có thể không hoàn toàn hiểu được từ ngữ của bạn, nhưng không chuyển tiếp (và nó sẽ không * luôn *) giải quyết cho cùng một điều như std :: di chuyển trong một ctor di chuyển (cast to rvalue)? Lưu ý phụ: VS2010 có vẻ (không chính xác?) Chấp nhận nhà điều hành số 2 của bạn là nhà cung cấp dịch vụ di chuyển khi số 1 không có mặt. – David

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