Оператор присваивания изменяет значение назначенного объекта - PullRequest
1 голос
/ 25 марта 2019

Я реализовал класс для обработки некоторых внешних функций (например, другой DLL).Эта функция дает мне целое число, которое я могу использовать как дескриптор.Вот важная часть моего кода:

MyClass
{
public:
    MyClass() { 
        handle = getHandlefromExternalFunction();
    }
    ~MyClass {
        if(handle>0)
            freeHandleFromExternalFunction(handle);
    }
    MyClass& operator=(MyClass& other) {
        freeHandleFromExternalFunction(handle);
        handle = other.handle
        other.handle = 0; //Is this a bad idea?
    }
private:
    int handle;
}

В моей основной функции у меня есть объект myClass.В какой-то момент я использую оператор присваивания, чтобы изменить значения объекта:

MyClass object;
//some code
object = MyClass();

После присвоения объект, созданный с помощью MyClass(), немедленно уничтожается, поскольку выходит из области видимости.Но я не хочу, чтобы freeHandleFromExternalFunction() вызывался для этого handle, поскольку я использую его в назначенном объекте.Для этого я изменяю значение назначенного объекта в операторе присваивания handle = 0.Мой вопрос: это плохая идея?У кого-нибудь есть лучшее решение для моей проблемы?

Ответы [ 2 ]

6 голосов
/ 25 марта 2019

Да, это плохая идея. Обычно вы не ожидаете, что правая часть задания будет изменена.

Если вы хотите переместить владение , используйте оператор присваивания «переместить» вместе с std::move:

MyClass& operator=(MyClass&& other) { ... }

// ...

MyClass a = ...;
MyClass b;

b = std::move(a);

Если вы только хотите такое движение (где может быть только один владелец содержащегося ресурса), то я также предлагаю вам пометить операторы конструктора копирования и назначения копирования как удаленные:

MyClass& operator=(MyClass const&) = delete;
MyClass(MyClass const&) = delete;

И, следуя правилу пяти , не забудьте о конструкторе перемещения и деструкторе:

~MyClass() { ... }
MyClass(MyClass&& other) { ... }
1 голос
/ 25 марта 2019
class MyClass {
public:
   //....
   MyClass& operator=(MyClass& other)

Неконстантный other в задании - плохая идея, и он может легко удивить программиста.Большинство программистов не ожидают, что правая часть присвоения будет видоизменена.

Также это не скомпилирует:

MyClass obj;
obj = MyClass(); // error 

Для того, чтобы это скомпилировать, вы должны использовать семантику перемещения, котораяВероятно, это то, что вы имели в виду с самого начала: class MyClass2 {public: // .... MyClass2 & operator = (const MyClass2 & other) = delete;MyClass2 & operator = (MyClass2 && other)

&& означает, что other может быть очищен в процессе:

 MyClass2 obj, obj2, obj3;
 obj = MyClass2(); // ok. Will be moved
 obj2 =std::move(obj); // ok
 obj3 = obj2; // error, not an rvalue rference (not MyClass2 &&)

Убедитесь, что два объекта не содержат одинаковый дескриптор.Убедитесь, что копия и назначение удалены, и переместите назначение и переместите конструктор, чтобы аннулировать дескриптор правой стороны.

Ваш объект должен иметь дескриптор.У ручки должен быть только один владелец.

...