如何使用shared_ptr或推荐另一种方法(unique_ptr)

时间:2017-06-16 10:21:36

标签: c++

UPD: 所以解决方案的要点是:如果存在复制构造函数,它会阻止std::move调用移动构造函数。问题解决了。
我已经尝试根据讲师的要求编写“线程安全堆栈”:

  1. 它应该存储类型本身。
  2. 对于原始类型,它应该通过副本接收/返回(通常在c中)
  3. 对于类类型,它不应该在接收/返回时调用冗余的复制构造函数。使用shared_ptr来实现此目标。
  4. 我不能让3号工作。

    更具体一点:我不知道如何将shared_ptr传递给这样设计的类。而且我几乎可以肯定我已经在语法上错误地编写了类。

    #ifndef SAFE_QUEUE
    #define SAFE_QUEUE
    
    #include <condition_variable>
    #include <thread>
    #include <stdlib.h>
    #include <queue>
    #include <mutex>
    #include <chrono>
    
    template<typename T>
    class SafeQueue {
    
    public:
        SafeQueue() {
            printf("CONSTRUCTOR\n");
        }
    
        ~SafeQueue() {
            printf("DESTRUCTOR\n");
        }
    
        void push(T data) {
            std::unique_lock<std::mutex> lock(_m);
            _queue.push(data);
            printf("Pushed %d\n", data);
            _cv.notify_one();
        }
    
        void push(std::shared_ptr<T> data) {
            std::unique_lock<std::mutex> lock(_m);
            _queue.push(*data);
            _cv.notify_one();
        }
    
        bool pop_top(T &outEl) {
            std::unique_lock<std::mutex> lock(_m);
            while (1) {
                bool a;
                if (a = this->_cv.wait_for(lock, std::chrono::milliseconds(1000),
                                           [this]() -> bool { return !(this->_queue.empty()); })) {
                    printf(" \n\n//Wait for returned %d \n", a);
                    if (!(_queue.empty())) {
                        outEl = _queue.front();
                        _queue.pop();
                        return true;
                    } else {
                        continue;
                    }
                } else {
                    printf(" \n\n//Wait for returned %d \n", a);
                    printf("Queue is empty\n");
                    return false;
                }
            }
        }
    
        std::shared_ptr<T> pop_top() {
            std::unique_lock<std::mutex> lock(_m);
            while (1) {
                bool a;
                if (a = this->_cv.wait_for(lock, std::chrono::milliseconds(1000),
                                           [this]() -> bool { return !(this->_queue.empty()); })) {
                    printf(" \n\n//Wait for returned %d \n", a);
                    if (!(_queue.empty())) {
                        std::shared_ptr<T> cur = std::make_shared<T>(_queue.front());
                        _queue.pop();
    
                        return cur;
                    } else {
                        continue;
                    }
                } else {
                    printf(" \n\n//Wait for returned %d \n", a);
                    printf("Queue is empty\n");
                    return nullptr;
                }
            }
        }
    
    private:
        std::queue<T> _queue;
        std::condition_variable _cv;
        std::mutex _m;
    };
    
    
    #endif
    

    主:

    #include <iostream>
    #include "safeQueue.h"
    #include <vector>
    
    
    void forEven(SafeQueue<int> *sq, int numThread){
        // for(int i=0;i<3;i++)
        //  sq->push(i+numThread);
        // sq->push(1);
        // for(int i=0;i<2;i++)
        //sq->push(numThread);
        int z;
        if(sq->pop_top(z))
        printf("even popped:%d\n", z);
        sq->push(numThread);
        printf("even pushed:%d\n", numThread);
    }
    
    class myclass{
    public:
        int val;
        myclass(myclass &obj){
            printf("copy constructor");
        }
        myclass(int val):val(val){
            printf("constructor");
        }
        ~myclass(){
            printf("destructor");
        }
    };
    
    void forOdd(SafeQueue<int> *sq, int numThread){
        int z;
        if(sq->pop_top(z))
        printf("odd popped:%d\n", z);
        if(sq->pop_top(z))
        printf("odd popped:%d\n", z);
    
    
        for(int i=0;i<2;i++) {
            sq->push(i + numThread);
            printf("odd pushed:%d\n", i + numThread);
        }
    
        if(sq->pop_top(z))
        printf("odd popped:%d\n", z);
        if(sq->pop_top(z))
    
    printf("odd popped:%d\n", z);
    }
    
    void forEven_class(SafeQueue<myclass> *sq, myclass &el){
        // for(int i=0;i<3;i++)
        //  sq->push(i+numThread);
        // sq->push(1);
        // for(int i=0;i<2;i++)
        //sq->push(numThread);
        std::shared_ptr<myclass> z = std::move(sq->pop_top());
        if(z)
            printf("even popped:%d\n", z->val);
        sq->push(std::make_shared<myclass>(el));
        printf("even pushed:%d\n", el.val);
    }
    
    void forOdd_class(SafeQueue<myclass> *sq, myclass &el){
        std::shared_ptr<myclass> z = std::move(sq->pop_top());
        if(z)
        printf("odd popped:%d\n", z->val);
        z = std::move(sq->pop_top());
        if(z)
            printf("odd popped:%d\n", z->val);
    
    
        for(int i=0;i<2;i++) {
            sq->push(std::make_shared<myclass>(i + el.val));
            printf("odd pushed:%d\n", i + el.val);
        }
    
        z = std::move(sq->pop_top());
        if(z)
            printf("odd popped:%d\n", z->val);
        z = std::move(sq->pop_top());
        if(z)
            printf("odd popped:%d\n", z->val);
    }
    
    int main(){
        SafeQueue<int> sq;
    
        SafeQueue<myclass> sq_c;
    
        std::vector<std::thread> v_t;
    
        for(int i=0;i<5;i++){
            if( i%2 )
                v_t.push_back(move(std::thread(forOdd,&sq,i+1)));
            else
                v_t.push_back(move(std::thread(forEven,&sq,i+1)));
        }
    
        for(int i=0;i<5;i++){
            v_t[i].join();
        }
    
        std::cout << "class test" <<std::endl;
        for(int i=0;i<5;i++){
            if( i%2 )
                v_t.push_back(move(std::thread(forOdd_class,&sq_c,std::move(myclass(i+1)))));
            else
                v_t.push_back(move(std::thread(forEven_class,&sq_c,std::move(myclass(i+1)))));
        }
    
        for(int i=0;i<5;i++){
            v_t[i].join();
        }
    
        // std::thread t1(forThreads,&sq,1);
        // std::thread t2(forThreads,&sq,2);
        // std::thread t3(forThreads,&sq,2);
        //
        // t1.join();
        // t2.join();
        // t3.join();
    
    
        return 0;
    }
    

    由于极端错误,我无法使forEven_class()和forOdd_class()工作:

    如果我只留下forEven / Odd_class函数的未注释定义,我得到:

    error: no matching function for call to ‘myclass::myclass(const myclass&)’
    

    所以似乎共享ptr尝试调用复制构造函数

    如果我取消注释,我会得到整体:

    In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:42:0,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional: In instantiation of ‘struct std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
           typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                                 ^
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1695:9: error: no type named ‘type’ in ‘class std::result_of<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
             _M_invoke(_Index_tuple<_Indices...>)
             ^
    In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:38:0,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘struct std::_Head_base<2ul, myclass, false>’:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:231:12:   recursively required from ‘struct std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass>’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:231:12:   required from ‘struct std::_Tuple_impl<0ul, void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass>’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:390:11:   required from ‘class std::tuple<void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass>’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1703:39:   required from ‘struct std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:137:17: error: ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 2ul; _Head = myclass]’ declared to take const reference, but implicit declaration would take non-const
           constexpr _Head_base(const _Head_base&) = default;
                     ^
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = myclass; long unsigned int _Idx = 2ul; _Head = myclass]’:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:273:42:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 2ul; _Head = myclass; _Tail = {}]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:900:43:   required by substitution of ‘template<class _Tp, class _Arg, class> static std::true_type std::__do_is_direct_constructible_impl::__test(int) [with _Tp = std::_Tuple_impl<2ul, myclass>; _Arg = std::_Tuple_impl<2ul, myclass>&&; <template-parameter-1-3> = <missing>]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:912:43:   required from ‘struct std::__is_direct_constructible_impl<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&>’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:134:12:   required from ‘struct std::__and_<std::is_destructible<std::_Tuple_impl<2ul, myclass> >, std::__is_direct_constructible_impl<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&> >’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:916:12:   required from ‘struct std::__is_direct_constructible_new_safe<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&>’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:994:12:   [ skipping 21 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:1175:12:   required from ‘struct std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass> >’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:134:12:   required from ‘struct std::__and_<std::is_nothrow_move_constructible<void (*)(SafeQueue<myclass>*, myclass&)>, std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass> > >’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:269:7:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 0ul; _Head = void (*)(SafeQueue<myclass>*, myclass&); _Tail = {SafeQueue<myclass>*, myclass}]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1727:41:   required from ‘typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:142:42: error: no matching function for call to ‘myclass::myclass(myclass)’
      : _M_head_impl(std::forward<_UHead>(__h)) { }
                                              ^
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:142:42: note: candidates are:
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
         myclass(int val):val(val){
         ^
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note:   no known conversion for argument 1 from ‘myclass’ to ‘int’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
         myclass(myclass &obj){
         ^
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note:   no known conversion for argument 1 from ‘myclass’ to ‘myclass&’
    In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:38:0,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with long unsigned int _Idx = 2ul; _Head = myclass]’:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:257:44:   recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 1ul; _Head = SafeQueue<myclass>*; _Tail = {myclass}]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:257:44:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 0ul; _Head = void (*)(SafeQueue<myclass>*, myclass&); _Tail = {SafeQueue<myclass>*, myclass}]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:400:33:   required from ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(const _Elements& ...) [with _Elements = {void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass}]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1678:74:   required from ‘std::_Bind_simple<_Callable(_Args ...)>::_Bind_simple(_Callable&&, _Args2&& ...) [with _Args2 = {SafeQueue<myclass>*, myclass}; <template-parameter-2-2> = void; _Callable = void (*)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1727:41:   required from ‘typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:135:25: error: no matching function for call to ‘myclass::myclass(const myclass&)’
           : _M_head_impl(__h) { }
                             ^
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:135:25: note: candidates are:
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
         myclass(int val):val(val){
         ^
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘int’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
         myclass(myclass &obj){
         ^
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’
    In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/x86_64-redhat-linux/bits/c++allocator.h:33:0,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/allocator.h:46,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/string:41,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/locale_classes.h:40,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/ios_base.h:41,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ios:42,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ostream:38,
                     from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/iostream:39,
                     from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:1:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = myclass; _Args = {const myclass&}; _Tp = myclass]’:
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_deque.h:1403:6:   required from ‘void std::deque<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = myclass; _Alloc = std::allocator<myclass>; std::deque<_Tp, _Alloc>::value_type = myclass]’
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_queue.h:216:9:   required from ‘void std::queue<_Tp, _Sequence>::push(const value_type&) [with _Tp = myclass; _Sequence = std::deque<myclass, std::allocator<myclass> >; std::queue<_Tp, _Sequence>::value_type = myclass]’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:37:9:   required from ‘void SafeQueue<T>::push(std::shared_ptr<_Tp1>) [with T = myclass]’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:69:43:   required from here
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120:4: error: no matching function for call to ‘myclass::myclass(const myclass&)’
      { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
        ^
    /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120:4: note: candidates are:
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
         myclass(int val):val(val){
         ^
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘int’
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
         myclass(myclass &obj){
         ^
    /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’
    

    所以我根本不知道如何使用shared_ptr。 (特别是将它传递给线程) 我可能会让讲师弄错了。那么你建议使用什么:unque_ptr或什么?

1 个答案:

答案 0 :(得分:1)

删除不必要的构造函数和析构函数,并更改forEven_class和forOdd_class的函数,代码将compile again
为什么删除构造函数?因为编译器有规则如何生成默认构造函数。在您的情况下,您希望生成移动构造函数,但通过定义复制构造函数和析构函数,您可以阻止编译器执行此操作。您的选择是:

  • 正确定义所有构造函数,包括移动构造函数
  • 删除复制构造函数和析构函数,因为他们没有做任何execpt首次输出
  • 指示编译器生成默认移动构造函数myclass(myclass &&obj) = default

automatic generation of move operations上查看此消息 我想要那些调试消息,然后你必须正确定义那些构造函数。包括除调试消息以外的其他任务。

关于函数forEven_class的更改,您不能通过引用获取myclass,因为它不是左值。有关此google rvalue参考的详细信息。