赋值运算符更改已分配对象的值

问题描述 投票:1回答:2

我实现了一个类来处理一些外部函数(例如另一个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;
}

在我的main函数中,我有一个myClass的对象。在某些时候,我使用assignement运算符来更改对象的值:

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

在分配之后,MyClass()创建的对象立即被销毁,因为它超出了范围。但我不希望在freeHandleFromExternalFunction()上调用handle,因为我在指定的对象中使用它。因此,我在assignement运算符handle = 0中更改指定对象的值。我的问题是:这是一个坏主意吗?有没有人能更好地解决我的问题?

c++ destructor assign
2个回答
6
投票

是的,这是一个坏主意。您通常不希望修改作业的右侧。

如果要移动所有权,请使用“移动”赋值运算符和std::move

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

// ...

MyClass a = ...;
MyClass b;

b = std::move(a);

如果您只想要这样的移动(其中只能包含所包含资源的一个所有者),那么我还建议您将复制构造函数和复制赋值运算符标记为已删除:

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

以下the rule of five不要忘记move-constructor和析构函数:

~MyClass() { ... }
MyClass(MyClass&& other) { ... }

1
投票
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 &&)

确保没有两个对象持有相同的句柄。确保删除复制和赋值,并移动赋值和移动构造函数使右侧句柄无效。

您的对象应该拥有句柄。句柄应该只有一个所有者。

© www.soinside.com 2019 - 2024. All rights reserved.