2013-08-19 101 views
10

Hãy xem xét mã thử nghiệm của tôi:Lỗi tạo std :: thread trên Mac OS X với kêu vang: "cố gắng sử dụng một chức năng xóa"

#include <thread> 

class Foo { 
public: 
    void threadFunc() {} 
    void startThread() { 
     _th = std::thread(&Foo::threadFunc, *this); 
    } 
private: 
    std::thread _th; 
}; 

int main(int argc, char *argv[]) 
{  
    Foo f; 
    f.startThread(); 
    return 0; 
} 

Đây là một lỗi nó tạo ra:

../untitled/main.cpp:13:14: warning: unused parameter 'argc' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
      ^
../untitled/main.cpp:13:26: warning: unused parameter 'argv' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
         ^
In file included from ../untitled/main.cpp:1: 
In file included from /usr/bin/../lib/c++/v1/thread:90: 
In file included from /usr/bin/../lib/c++/v1/__functional_base:15: 
/usr/bin/../lib/c++/v1/type_traits:1372:12: error: call to implicitly-deleted copy constructor of 'typename decay<Foo &>::type' (aka 'Foo') 
    return _VSTD::forward<_Tp>(__t); 
      ^~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/c++/v1/__config:273:15: note: expanded from macro '_VSTD' 
#define _VSTD std::_LIBCPP_NAMESPACE 
      ^
/usr/bin/../lib/c++/v1/thread:351:33: note: in instantiation of function template specialization 'std::__1::__decay_copy<Foo &>' requested here 
           __decay_copy(_VSTD::forward<_Args>(__args))...)); 
           ^
../untitled/main.cpp:7:15: note: in instantiation of function template specialization 'std::__1::thread::thread<void (Foo::*)(), Foo &, void>' requested here 
     _th = std::thread(&Foo::threadFunc, *this); 
      ^
../untitled/main.cpp:10:17: note: copy constructor of 'Foo' is implicitly deleted because field '_th' has an inaccessible copy constructor 
    std::thread _th; 
       ^

và nếu tôi tạo ra một chủ đề như thế này: _th = std::thread(&Foo::threadFunc, std::ref(*this));

tôi nhận được:

../untitled/main.cpp:13:14: warning: unused parameter 'argc' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
      ^
../untitled/main.cpp:13:26: warning: unused parameter 'argv' [-Wunused-parameter] 
int main(int argc, char *argv[]) 
         ^
In file included from ../untitled/main.cpp:1: 
/usr/bin/../lib/c++/v1/thread:330:5: error: attempt to use a deleted function 
    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 
    ^
/usr/bin/../lib/c++/v1/thread:340:5: note: in instantiation of function template specialization 'std::__1::__threaad_execute<void (Foo::*)(), std::__1::reference_wrapper<Foo> , 1>' requested here 
    __threaad_execute(*__p, _Index()); 
    ^
/usr/bin/../lib/c++/v1/thread:352:41: note: in instantiation of function template specialization 'std::__1::__thread_proxy<std::__1::tuple<void (Foo::*)(), std::__1::reference_wrapper<Foo> > >' requested here 
    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 
             ^
../untitled/main.cpp:7:15: note: in instantiation of function template specialization 'std::__1::thread::thread<void (Foo::*)(), std::__1::reference_wrapper<Foo> , void>' requested here 
     _th = std::thread(&Foo::threadFunc, std::ref(*this)); 
      ^
/usr/bin/../lib/c++/v1/type_traits:833:5: note: function has been explicitly marked deleted here 
    ~__nat() = delete; 
    ^

Tôi đang làm gì sai? Tôi không có vấn đề như vậy trên Windows với VS2012. Tôi cũng không có vấn đề này với việc thực thi stdlib mặc định trên Mac, nhưng bây giờ tôi phải sử dụng libC++.

cờ biên dịch của tôi: -std=c++11 -mmacosx-version-min=10.7 -stdlib=libc++

+1

Phiên bản (tuân thủ chuẩn) với 'std :: ref' [hoạt động chính xác trên Coliru] (http://coliru.stacked-crooked.com/view ? id = 61d9f8137948ff6540e8c2235ff01bdd-e1204655eaff68246b392dc70c5a32c9), bạn có thể gặp lỗi trong trình biên dịch/stdlib của bạn. – Casey

Trả lời

11
_th = std::thread(&Foo::threadFunc, *this); 

này sẽ cố gắng để tạo ra một bản sao của *this để lưu trữ trong đối tượng chủ đề mới, nhưng kiểu của bạn là không copyable vì thành viên _th không copyable.

Bạn có thể muốn lưu trữ một con trỏ đến đối tượng, không phải là một bản sao của đối tượng:

_th = std::thread(&Foo::threadFunc, this); 

N.B. chương trình của bạn sẽ chấm dứt vì bạn không tham gia chuỗi. Trong loại hủy của bạn, bạn nên làm điều gì đó như:

~Foo() { if (_th.joinable()) _th.join(); } 
+0

Tôi nghĩ rằng 'thread' mong đợi một tham chiếu đến một lớp, không phải là một con trỏ. Cảm ơn. –

+0

Không, nó mong đợi bất kỳ loại có thể gọi nào, và một con trỏ hàm thành viên như '& Foo :: threadFunc' có thể được gọi với đối số của kiểu' Foo' hoặc 'Foo &' hoặc 'Foo *'. Bạn có thể chuyển một tham chiếu nếu bạn muốn, nhưng đó không phải là mã của bạn. Nếu bạn muốn chuyển một tham chiếu sử dụng 'std :: thread (& Foo :: threadFunc, std :: ref (* this));' do đó, nó không cố gắng tạo một bản sao. –

+1

Như bạn thấy trong câu hỏi, tôi đã thử 'std :: ref' và nó cũng không hoạt động. –