赋值运算符改变赋值对象的值
Assignement operator changing value of the assigned object
我实现了一个 class 来处理一些外部函数(例如另一个 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
中更改了赋值对象的值。我的问题是:这是个坏主意吗?有人有更好的解决方案吗?
是的,这是个坏主意。您通常不希望修改赋值的右侧。
如果你想移动所有权然后使用"move"赋值运算符连同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 不要忘记移动构造函数和析构函数:
~MyClass() { ... }
MyClass(MyClass&& other) { ... }
class MyClass {
public:
//....
MyClass& operator=(MyClass& other)
赋值中的非常量 other
是个坏主意,很容易让程序员大吃一惊。大多数程序员不希望赋值的右侧发生变化。
这也不会编译:
MyClass obj;
obj = MyClass(); // error
要进行编译,您必须使用移动语义,这可能是您一开始的意思:
class MyClass2 {
public:
//....
MyClass2& operator=(const MyClass2& other) = delete;
MyClass2& 运算符=(MyClass2&& 其他)
&&表示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 &&)
确保没有两个对象拥有相同的句柄。确保删除复制和赋值,移动赋值和移动构造函数使右侧的句柄无效。
您的对象应该拥有 句柄。句柄应该只有一个所有者。
我实现了一个 class 来处理一些外部函数(例如另一个 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
中更改了赋值对象的值。我的问题是:这是个坏主意吗?有人有更好的解决方案吗?
是的,这是个坏主意。您通常不希望修改赋值的右侧。
如果你想移动所有权然后使用"move"赋值运算符连同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 不要忘记移动构造函数和析构函数:
~MyClass() { ... }
MyClass(MyClass&& other) { ... }
class MyClass {
public:
//....
MyClass& operator=(MyClass& other)
赋值中的非常量 other
是个坏主意,很容易让程序员大吃一惊。大多数程序员不希望赋值的右侧发生变化。
这也不会编译:
MyClass obj;
obj = MyClass(); // error
要进行编译,您必须使用移动语义,这可能是您一开始的意思: class MyClass2 { public: //.... MyClass2& operator=(const MyClass2& other) = delete; MyClass2& 运算符=(MyClass2&& 其他)
&&表示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 &&)
确保没有两个对象拥有相同的句柄。确保删除复制和赋值,移动赋值和移动构造函数使右侧的句柄无效。
您的对象应该拥有 句柄。句柄应该只有一个所有者。