2010-07-19 27 views
145

Điều gì xảy ra với chương trình này?Tại sao tôi không thể push_back một unique_ptr thành một vectơ?

#include <memory> 
#include <vector> 

int main() 
{ 
    std::vector<std::unique_ptr<int>> vec; 

    int x(1); 
    std::unique_ptr<int> ptr2x(&x); 
    vec.push_back(ptr2x); //This tiny command has a vicious error. 

    return 0; 
} 

Lỗi:

$ g++ -std=gnu++0x main.cpp 
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c+ 
+/mingw32/bits/c++allocator.h:34:0, 
       from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c+ 
+/bits/allocator.h:48, 
       from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c+ 
+/memory:64, 
       from main.cpp:6: 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h: I 
n member function 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, 
const _Tp&) [with _Tp = std::unique_ptr<int>, _Tp* = std::unique_ptr< 
int>*]': 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/stl_vector.h:74 
5:6: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(con 
st value_type&) [with _Tp = std::unique_ptr<int>, _Alloc = std::alloca 
tor<std::unique_ptr<int> >, value_type = std::unique_ptr<int>]' 
main.cpp:16:21: instantiated from here 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h:20 
7:7: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::uniqu 
e_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_D 
eleter = std::default_delete<int>, std::unique_ptr<_Tp, _Tp_Deleter> = 
std::unique_ptr<int>]' 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/ext/new_allocator.h: 
105:9: error: used here 
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c+ 
+/vector:69:0, 
       from main.cpp:7: 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h: I 
n member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::v 
ector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const std::u 
nique_ptr<int>&}, _Tp = std::unique_ptr<int>, _Alloc = std::allocator< 
std::unique_ptr<int> >, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx 
::__normal_iterator<std::unique_ptr<int>*, std::vector<std::unique_ptr 
<int> > >, typename std::vector<_Tp, _Alloc>::_Base::_Tp_alloc_type::p 
ointer = std::unique_ptr<int>*]': 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/stl_vector.h:74 
9:4: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(con 
st value_type&) [with _Tp = std::unique_ptr<int>, _Alloc = std::alloca 
tor<std::unique_ptr<int> >, value_type = std::unique_ptr<int>]' 
main.cpp:16:21: instantiated from here 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h:20 
7:7: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::uniqu 
e_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_D 
eleter = std::default_delete<int>, std::unique_ptr<_Tp, _Tp_Deleter> = 
std::unique_ptr<int>]' 
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/vector.tcc:314: 
4: error: used here 

Trả lời

238

Bạn cần phải di chuyển unique_ptr:

vec.push_back(std::move(ptr2x)); 

unique_ptr đảm bảo rằng một unique_ptr chứa duy nhất có quyền sở hữu của con trỏ tổ chức. Điều này có nghĩa là bạn không thể tạo bản sao của unique_ptr (vì sau đó hai unique_ptr s sẽ có quyền sở hữu), vì vậy bạn chỉ có thể di chuyển nó.

Lưu ý, tuy nhiên, việc sử dụng unique_ptr hiện tại của bạn không chính xác. Bạn không thể sử dụng nó để quản lý một con trỏ đến một biến cục bộ. Vòng đời của biến cục bộ được quản lý tự động: biến địa phương bị hủy khi khối kết thúc (ví dụ: khi hàm trả về, trong trường hợp này). Bạn cần phân bổ động đối tượng:

std::unique_ptr<int> ptr(new int(1)); 
+11

Vì chỉ có thể có một, người ta cũng có thể truyền trực tiếp tạm thời cho vectơ: 'vec.push_back (std :: unique_ptr (int mới (1))); 'unique_ptr' cũng có thể sử dụng một deleter tùy chỉnh (mà không có gì), nhưng sau đó người ta phải đưa vào tài khoản rằng địa chỉ của biến địa phương trở thành không hợp lệ ở phần cuối của phạm vi. – UncleBens

+17

Một tùy chọn khác là sử dụng 'emplace_back'. ví dụ. 'vec.emplace_back (int mới (1)); ' –

+60

@deft_code: Không, điều đó không an toàn. Thao tác 'emplace_back' có thể ném, và nếu nó hoạt động,' int' được phân bổ động sẽ bị rò rỉ. Quy tắc chung là tất cả các phân bổ động phải được sở hữu bởi một con trỏ thông minh có tên để tránh rò rỉ. –

15

std::unique_ptr không có hàm tạo bản sao. Bạn tạo một cá thể và sau đó yêu cầu std::vector để sao chép trường hợp đó trong quá trình khởi tạo.

error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::uniqu 
e_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_D 
eleter = std::default_delete<int>, std::unique_ptr<_Tp, _Tp_Deleter> = 
std::unique_ptr<int>]' 

The class satisfies the requirements of MoveConstructible and MoveAssignable, but not the requirements of either CopyConstructible or CopyAssignable.

Các công trình sau đây với emplace cuộc gọi mới.

std::vector< std::unique_ptr<int> > vec; 
vec.emplace_back(new int(1984)); 

Xem using unique_ptr with standard library containers để đọc thêm.

+1

Xem [bình luận này] (https://stackoverflow.com/questions/3283778/why-can-i-not -push-back-a-unique-ptr-into-a-vector # comment11813799_3283795) - sử dụng các hàm 'emplace_x()' không an toàn khi sử dụng con trỏ thông minh. – Qix

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