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

C++20下如何避免Split方法返回CList时触发两次昂贵拷贝构造?

问题背景

现有代码实现了字符串分割功能:

CList<CString> Split(char delim) {
    CList<CString> subStrings;
    for (char* ps = Buffer(); *ps; ps++) {
        char* pe;
        for (pe = ps; *pe && (*pe != delim); pe++)
            ;
        subStrings.Append(CString(ps, int(pe - ps)));
        if (!*pe)
            break;
        ps = pe;
    }
    return subStrings;
}

// 调用代码
CList<CString> values = s.Split(';');

上述代码执行调用逻辑时会触发两次CList拷贝构造:

  1. Split方法内栈上局部变量subStrings离开作用域时,被拷贝到编译器维护的临时存储区
  2. 临时对象再拷贝到values变量

编译环境已支持C++20标准,要求不做根本性代码改动(如新增输出参数)的前提下,消除这两次拷贝开销。

解决方案
  • 方案1:为CList类实现移动构造函数和移动赋值运算符
    只要给CList补充符合C++标准的移动语义实现,无需修改现有业务代码,编译器就会优先用移动构造代替拷贝构造。移动操作仅会转移列表内部的资源指针,不会复制元素,开销极低。如果使用的是MFC原生不支持移动的CList,可以简单继承封装一个支持移动的子类,原有Split方法的返回值声明、调用代码都无需调整。

  • 方案2:开启编译器返回值优化(RVO)
    C++17及以上标准已将*具名返回值优化(NRVO)*列为标准支持的优化项,主流编译器(MSVC、GCC、Clang)在O2及以上优化等级下,会直接将Split内部的subStrings对象构造在外部values的内存地址上,完全消除两次拷贝操作,不需要修改任何代码。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 15:06:03