2014-05-09 19 views
6

Hãy xem xét đoạn mã sau C++ 11:Tại sao mã này sẽ không biên dịch nếu destructor được khai báo?

#include <thread> 
#include <vector> 

struct A { 
    A() {} 

    //virtual ~A() = default; 
    //~A() = default; 
    //~A() {}; 

    std::thread t; 
}; 

int main() 
{ 
    std::vector<A> v; 
    v.emplace_back(); 
} 

Nếu bất kỳ của các dòng tuyên bố destructor trên mã trước đây là không chú thích, mã này sẽ không biên dịch. Trình biên dịch phàn nàn về bản sao construtor của std::thread bị xóa. Nhưng std::vector::emplace_back sẽ không sử dụng hàm tạo bản sao, vì vậy, tại sao nó không thành công? Và tại sao heck đề cập đến các destructor vấn đề?

đầu ra GCC (~A() {}; không chú thích):

$ g++ --std=c++11 -o test test.cpp 
In file included from /usr/include/c++/4.8/memory:64:0, 
       from /usr/include/c++/4.8/thread:40, 
       from test.cpp:1: 
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]’: 
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; bool _TrivialValueTypes = false]’ 
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*]’ 
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; _Tp = A]’ 
/usr/include/c++/4.8/bits/stl_uninitialized.h:281:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = A*; _ForwardIterator = A*; _Allocator = std::allocator<A>]’ 
/usr/include/c++/4.8/bits/vector.tcc:415:43: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {}; _Tp = A; _Alloc = std::allocator<A>]’ 
/usr/include/c++/4.8/bits/vector.tcc:101:54: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = A; _Alloc = std::allocator<A>]’ 
test.cpp:17:17: required from here 
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(const A&)’ 
    { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } 
    ^
test.cpp:4:8: note: ‘A::A(const A&)’ is implicitly deleted because the default definition would be ill-formed: 
struct A { 
     ^
test.cpp:4:8: error: use of deleted function ‘std::thread::thread(const std::thread&)’ 
In file included from test.cpp:1:0: 
/usr/include/c++/4.8/thread:126:5: error: declared here 
    thread(const thread&) = delete; 
    ^

Clang đầu ra (~A() {}; không chú thích):

$ clang++ --std=c++11 -o test test.cpp 
In file included from test.cpp:1: 
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:40: 
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/memory:64: 
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_construct.h:75:38: error: 
     call to implicitly-deleted copy constructor of 'A' 
    { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } 
            ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:75:8: note: 
     in instantiation of function template specialization 
     'std::_Construct<A, A>' requested here 
       std::_Construct(std::__addressof(*__cur), *__first); 
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:117:2: note: 
     in instantiation of function template specialization 
     'std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<A *>, 
     A *>' requested here 
     __uninit_copy(__first, __last, __result); 
     ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:258:19: note: 
     in instantiation of function template specialization 
     'std::uninitialized_copy<std::move_iterator<A *>, A *>' requested here 
    { return std::uninitialized_copy(__first, __last, __result); } 
       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:279:19: note: 
     in instantiation of function template specialization 
     'std::__uninitialized_copy_a<std::move_iterator<A *>, A *, A>' requested 
     here 
     return std::__uninitialized_copy_a 
       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:413:15: note: 
     in instantiation of function template specialization 
     'std::__uninitialized_move_if_noexcept_a<A *, A *, std::allocator<A> >' 
     requested here 
       = std::__uninitialized_move_if_noexcept_a 
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:101:4: note: 
     in instantiation of function template specialization 'std::vector<A, 
     std::allocator<A> >::_M_emplace_back_aux<>' requested here 
      _M_emplace_back_aux(std::forward<_Args>(__args)...); 
     ^
test.cpp:17:4: note: in instantiation of function template specialization 
     'std::vector<A, std::allocator<A> >::emplace_back<>' requested here 
     v.emplace_back(); 
     ^
test.cpp:11:14: note: copy constructor of 'A' is implicitly deleted because 
     field 't' has a deleted copy constructor 
     std::thread t; 
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:126:5: note: 
     'thread' has been explicitly marked deleted here 
    thread(const thread&) = delete; 
    ^
1 error generated. 
+5

Đặc điểm kỹ thuật rõ ràng của trình phá hủy ngăn cản trình dịch chuyển-trình biên dịch tổng hợp. Bạn sẽ phải thêm một tài khoản theo cách thủ công. – 0x499602D2

+0

Cảm ơn. Thêm 'A (A && o) = mặc định;' đã giải quyết được vấn đề của tôi. – lvella

Trả lời

6

(trả lời lấy từ ý kiến, không có tín dụng được thực hiện bởi tôi)

Nếu một destructor được khai báo theo cách thủ công, hàm khởi tạo mặc định không được tạo khi biên dịch. Việc buộc hàm khởi tạo mặc định được sử dụng sẽ sửa lỗi này:

A(A&& o) = default; 
+2

Có thể đáng nói rằng mã sẽ hoạt động nếu A có một thành viên có thể sao chép thay vì std :: thread vì hàm tạo bản sao của A sẽ không bị xóa hoàn toàn trong trường hợp đó (tôi không muốn chỉnh sửa câu trả lời từ điện thoại của mình). – jrok

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