gpt4 book ai didi

c++ - 为什么禁用 CObject 的复制构造函数和赋值

转载 作者:可可西里 更新时间:2023-11-01 17:43:15 25 4
gpt4 key购买 nike

默认禁用MFC根对象CObject的拷贝构造函数和赋值。

The standard C++ default class copy constructor does a member-by-member copy. The presence of the private CObject copy constructor guarantees a compiler error message if the copy constructor of your class is needed but not available. You must therefore provide a copy constructor if your class requires this capability.

  • 在CObject的源码中,有一句注释:

Disable the copy constructor and assignment by default so you will get compiler errors instead of unexpected behaviour if you pass objects by value or assign objects.

我的问题是,这个 CObject 类的默认逐位复制构造函数有什么问题?在我看来,最好给我们一个默认的复制构造函数,如果需要的话我们可以提供一个(深复制)

最佳答案

默认的复制构造函数是逐个成员的,而不是按位的。

大多数 CObject 派生类包含 - 并直接管理 - 一些没有引用计数或类似机制的系统资源,因此做出选择时可能考虑了默认用例。

例如CGDIObject 大致是:

class CGDIObject : public CObject
{
HGDIOBJ m_handle;

CGDIObject() : m_handle(0) {}
// derived classes provide a create, attach etc.
~CGDIObject() { DeleteObject(m_handle); }
}

此处的默认复制构造函数是危险的(导致双重破坏),提供“正确”的复制构造函数出奇地困难且昂贵。

另一个原因可能是大多数 CObject 派生类都旨在进行变异,因此通过引用传递。缺少的复制构造函数将捕获意外的拷贝,这些拷贝会改变拷贝而不是传递的对象:

class CMyObject : public CObject
{
public:
AttachFoo(FooHandle foo) { ... }
AddBar() { ... }
};

bool InitMySession(CMyObject & obj)
{
obj.AttachFoo(CreateRawFoo());
obj.AddBar();
obj.AddBar();
}

// ...
CMyObj mo;
InitMySession(mo);

省略“&”会让你的代码编译得很好,但会创建一个临时拷贝,修改它,然后删除它,而 mo 保持不变。

很多 API 都遵循这种模式,因为 MFC 不依赖异常进行错误处理(由于历史原因:并非所有目标编译器都很好地支持它们,并且 MFC 需要大量额外的资源处理,异常会变得很痛苦) .


我认为这些选择都不好,例如如果派生类的成员允许(并且大多数成员应该允许),应该允许派生类使用默认的复制构造函数。

不过,该决定符合 MFC 的“思维模式”,以及创建 MFC 时的要求/限制。

关于c++ - 为什么禁用 CObject 的复制构造函数和赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3085257/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com