нет совпадения с оператором = - PullRequest
1 голос
/ 08 октября 2019

В следующем примере я пытаюсь, если я пытаюсь вернуться по ссылке из fun(), тогда он выдает мне предупреждение, как и должно.

Однако, когда я пытаюсь вернуться по значению, я ожидаю 'operator=() 'срабатывает, но выдает следующую ошибку, которую я не могу понять, почему:

error: no match for ‘operator=’ (operand types are ‘Auto_ptr2<Resource>’ and ‘Auto_ptr2<Resource>’)

note: no known conversion for argument 1 from ‘Auto_ptr2<Resource>’ to 
‘Auto_ptr2<Resource>&’

Удивительно, но res2=res1 вызвал' operator = () 'просто отлично !! !

template<class T>
class Auto_ptr2
{
        T* m_ptr;
public:
        Auto_ptr2(T* ptr=nullptr)
                :m_ptr(ptr)
        {std::cout<<"\nAuto_ptr CTOR called ";}
        ~Auto_ptr2()
        {
                std::cout<<"\n~Auto_ptr2 called\n";
                delete m_ptr;
        }
        // A copy constructor that implements move semantics
        Auto_ptr2(Auto_ptr2& 
        {
                std::cout<<"\nAuto_PTR2 copy constructor called";
                m_ptr = a.m_ptr; 
                a.m_ptr = nullptr; 
        }
        Auto_ptr2& operator=(Auto_ptr2& a) 
        {
                std::cout<<"\nAuto_ptr2 operator = called";
                if (&a == this)
                        return *this;
                delete m_ptr; 
                m_ptr = a.m_ptr; 
                a.m_ptr = nullptr; 
                return *this;
        }

        T& operator*() const { return *m_ptr; }
        T* operator->() const { return m_ptr; }
        bool isNull() const { return m_ptr == nullptr;  }
};
class Resource
{
public:
        Resource() { std::cout << "\nResource acquired"; }
        ~Resource() { std::cout << "\nResource destroyed"; }
};

Auto_ptr2<Resource> fun(Auto_ptr2<Resource> res3)
{
        std::cout << "\nres1 is " << (res3.isNull() ? "null" : "not null");
        return res3;
}

int main()
{
        Auto_ptr2<Resource> res1(new Resource);
        Auto_ptr2<Resource> res2; 

        res2 = res1; // res2 assumes ownership, res1 is set to null

        res2=fun(res2); //ERROR : error: no match for ‘operator=’ (operand types are ‘Auto_ptr2<Resource>’ and ‘Auto_ptr2<Resource>’)


        return 0;
}

1 Ответ

2 голосов
/ 08 октября 2019

Если я правильно понимаю, вы пишете что-то похожее на std::unique_ptr.

Так что, что касается std::unique_ptr, operator=() должен работать с семантикой перемещения, поэтому получение ссылки на r-vale, Auto_ptr &&, а не ссылка на l-значение

     Auto_ptr2& operator=(Auto_ptr2 && a) 
    {
            std::cout<<"\nAuto_ptr2 operator = called";
            if (&a == this)
                    return *this;
            delete m_ptr; 
            m_ptr = a.m_ptr; 
            a.m_ptr = nullptr; 
            return *this;
    }

И использование должно проходить через std::move()

res2=fun(std::move(res2));

Та же проблема с конструкторами: избегайте копирования конструктора (возможно, удалите его)) и написать конструктор перемещения.

    Auto_ptr2 (Auto_ptr2 const &) = delete;

    Auto_ptr2 (Auto_ptr2 && a) 
    {
            std::cout<<"\nAuto_PTR2 move constructor called";
            m_ptr = a.m_ptr; 
            a.m_ptr = nullptr; 
    }
...