2013-08-16 25 views
16

Cách thích hợp để chuyển quyền sở hữu của một std::vector<unique_ptr<int> > cho một lớp học đang được xây dựng là gì?Cách thích hợp để chuyển quyền sở hữu của một tiêu chuẩn :: vectơ <std :: unique_ptr < int>> đến một lớp học đang được xây dựng

Dưới đây là mã đại diện cho những gì tôi muốn làm. Tôi nhận ra nó không chính xác (sẽ không biên dịch) và vi phạm "tính duy nhất" cho dù tôi truyền vectơ cho hàm tạo theo giá trị hay tham chiếu. Tôi muốn Foo là chủ sở hữu mới của vectơ, và muốn có chức năng gọi điện để từ bỏ quyền sở hữu. Tôi có cần người xây dựng để lấy số std::unique_ptr<std::vector<std::unique_ptr<int> > > để làm điều này không?

foo.h

class Foo 
{ 
public: 
    Foo(vector<std::unique_ptr<int> > vecOfIntPtrsOwnedByCaller); 

private: 
    vector<std::unique_ptr<int> > _vecOfIntPtrsOwnedByFoo; 
} 

Foo.cpp

Foo::Foo(std::vector<std::unique_ptr< int> > vecOfIntPtrsOwnedByCaller) 
{ 
    _vecOfIntPtrsOwnedByFoo = vecOfIntPtrsOwnedByCaller; 
} 

Bất kỳ trợ giúp sẽ được nhiều đánh giá cao - Tôi đã lùng sục mạng tìm kiếm cách chính xác để làm điều này. Cảm ơn!

+1

'std :: vector > 'đòi hỏi một trong hai tạm thời hoặc người gọi sử dụng 'std :: move' trên vector của riêng họ, vì nó không thể được sao chép. Nếu bạn muốn làm cho nó thực sự rõ ràng, hãy xem xét' std :: vector <...> && '. Sau đó, di chuyển vào thành viên của bạn (trong thành viên-initializers!) Với 'std :: move'. – Xeo

+1

Bạn có muốn vectơ được sở hữu độc quyền hay các phần tử chứa trong đó không? –

+0

Cuộc đua nhẹ nhàng trong Orbit - Cả hai. – Jen

Trả lời

16

std::unique_ptr<T> là loại không thể sao chép được nhưng có thể di chuyển. Chỉ có loại di chuyển trong một số std:vector<T> cũng chỉ làm cho số std::vector<T> chỉ di chuyển. Để trình biên dịch tự động di chuyển các đối tượng, bạn cần phải có giá trị r để di chuyển-xây dựng hoặc di chuyển-chuyển nhượng. Trong hàm dựng của bạn, đối tượng vecOfIntPtrsOwnedByCaller là một giá trị l, mặc dù tên của nó, đã có tên là int s: chúng bị "đánh cắp" từ người gọi khi người gọi tạo đối tượng. Để di chuyển từ một l-giá trị, bạn cần phải sử dụng std::move() (hoặc một cái gì đó tương đương):

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller) 
{ 
    _vecOfIntPtrsOwnedByFoo = std::move(vecOfIntPtrsOwnedByCaller); 
} 

hay, thích hợp hơn

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller) 
    : _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsOwnedByCaller)) 
{ 
} 

Cách tiếp cận thứ hai tránh mặc định-xây dựng đầu tiên các thành viên và sau đó move- gán cho nó và, thay vào đó, hãy di chuyển-xây dựng thành viên trực tiếp. Tôi đoán, tôi cũng sẽ làm cho các đối số một tham chiếu giá trị r nhưng điều này là không cần thiết.

Lưu ý, bạn có thể xây dựng các đối tượng của loại Foo chỉ từ một cái gì đó mà có thể được liên kết với một r có giá trị, ví dụ:

int main() { 
    Foo f0(std::vector<std::unique_ptr<int>>()); // OK 
    std::vector<std::unique_ptr<int>> v; 
    Foo f1(v); v// ERROR: using with an l-value 
    Foo f2{v}; v// ERROR: using with an l-value 
    Foo f3 = v; // ERROR: using with an l-value 
    Foo f4(std::move(v)); // OK: pretend that v is an r-value 
} 
+0

Giải pháp có tham chiếu và trao đổi có hợp lệ không? Tôi có nghĩa là 'Foo (vectơ > & v) {this-> v.swap (v); } '. Thành thật mà nói tôi biết câu trả lời của bạn là chính xác và tốt hơn - nhưng bằng cách sử dụng 'hoán đổi' cũng có thể là một cách để yêu cầu "chuyển quyền sở hữu" của OP? – PiotrNycz

+0

@PiotrNycz: Sử dụng 'std :: vector <...>' '' swap() 'cũng hoạt động, nhưng sử dụng' std :: move() 'trong danh sách initializer thành viên là cách thành ngữ để truyền tải nội dung. –

+0

Cảm ơn Dietmar, liệu bạn có thể cho thấy một ví dụ về một nhà xây dựng tham khảo một tham chiếu rvalue hay không và cách truyền một véc tơ cho nó? Bạn quyết định sử dụng phiên bản nào? – Jen

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