You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询C++11中强制对象仅可移动的代码实现是否正确

关于强制对象仅支持移动语义的实现疑问解答

嘿,你的CResource类实现强制仅支持移动语义的方式是正确的,但CAcquireResource里的AcquireResource返回右值引用的写法有坑,咱们一步步说:

1. CResource的实现没问题

你把拷贝构造和拷贝赋值运算符放在private域并标记为= delete,这确实能完全阻止外部代码对CResource对象进行拷贝操作——因为外部无法访问private成员,就算是友元也没法调用被delete的函数。

另外,显式声明移动构造和移动赋值运算符是个好习惯:虽然如果你的类成员都是可移动的,编译器会自动生成默认的移动操作,但显式声明能明确表达你的设计意图,也方便后续自己扩展移动逻辑(比如手动管理m_pResource的转移)。

不过有个小优化建议:可以把delete的拷贝操作放到public域里,这样外部代码尝试拷贝时,编译器会直接提示“函数已删除”,比因为private访问权限报错更直观,效果完全一样:

class CResource {
public:
    CResource();
    CResource(CResource &&);
    CResource & operator=(CResource &&);
    
    // 直接在public区标记删除,可读性更好
    CResource(const CResource &) = delete;
    CResource & operator=(const CResource &) = delete;
private:
    void * m_pResource;
};

2. CAcquireResource的AcquireResource写法有风险

返回CResource &&这种右值引用要格外小心,因为引用本身不持有对象的所有权。如果你的AcquireResource函数是这样实现的:

CResource && CAcquireResource::AcquireResource() {
    CResource res;
    // 初始化res...
    return std::move(res);
}

那函数结束后,局部对象res会被销毁,返回的右值引用就变成了悬垂引用,后续使用这个引用会导致未定义行为。

正确的做法是直接返回CResource对象:

class CAcquireResource {
public:
    CResource AcquireResource();
};

编译器会自动触发返回值优化(RVO),直接在调用方的内存空间构造对象,完全避免拷贝或移动操作;就算RVO没生效,编译器也会自动把返回的局部对象转为右值,调用移动构造函数,效率同样很高,而且不会有悬垂引用的问题。

总结一下:你的核心思路(禁用拷贝、开放移动)是对的,只是返回右值引用的地方需要调整成返回对象本身。

内容的提问来源于stack exchange,提问作者nearproc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:28:36