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

为何+运算符的右值引用重载未触发?如何利用其优化?

利用右值引用优化C++字符串类的+运算符

首先明确问题核心:你之前的operator+(Test&&)重载未被触发,大概率是因为重载形式不对——你需要的是让右值对象本身调用的operator+版本,而非接受右值参数的版本。下面直接给出正确的实现思路和代码示例。

核心优化思路

当表达式如str2 + "test"产生临时右值后,后续对这个右值的+操作应该直接复用其内存空间,而非创建新对象再拷贝。要实现这一点,需给成员函数operator+添加右值引用限定符(&&),标识该函数仅能被右值对象调用;同时提供左值版本的operator+处理常规场景。

完整实现示例

#include <cstring>
#include <iostream>

class Test {
private:
    char* data = nullptr;
    size_t len = 0;

public:
    // 基础构造
    Test(const char* s = "") : len(strlen(s)) {
        data = new char[len + 1];
        strcpy(data, s);
    }

    // 拷贝构造(左值拷贝)
    Test(const Test& other) : len(other.len) {
        data = new char[len + 1];
        strcpy(data, other.data);
        std::cout << "[触发] 拷贝构造" << std::endl;
    }

    // 移动构造(接管右值资源)
    Test(Test&& other) noexcept : data(other.data), len(other.len) {
        other.data = nullptr;
        other.len = 0;
        std::cout << "[触发] 移动构造" << std::endl;
    }

    // 析构
    ~Test() {
        delete[] data;
    }

    // 复用 += 逻辑,减少重复代码
    Test& operator+=(const Test& rhs) {
        char* new_buf = new char[len + rhs.len + 1];
        strcpy(new_buf, data);
        strcat(new_buf, rhs.data);
        delete[] data;
        data = new_buf;
        len += rhs.len;
        return *this;
    }

    // 左值对象调用的 +:创建新对象并拷贝
    Test operator+(const Test& rhs) & {
        Test res(*this);
        res += rhs;
        std::cout << "[触发] 左值版operator+" << std::endl;
        return res;
    }

    // 右值对象调用的 +:直接修改自身,移动返回
    Test operator+(const Test& rhs) && {
        std::move(*this) += rhs;
        std::cout << "[触发] 右值版operator+" << std::endl;
        return std::move(*this);
    }

    // 处理 const char* 的重载,同样区分左/右值
    Test operator+(const char* rhs) & {
        return *this + Test(rhs);
    }

    Test operator+(const char* rhs) && {
        return std::move(*this) + Test(rhs);
    }

    // 打印内容
    void print() const {
        std::cout << "内容:" << (data ? data : "") << std::endl;
    }
};

int main() {
    Test str2("hello");
    Test res = str2 + "test" + str2;
    res.print();
    return 0;
}

关键细节说明

  1. 右值引用限定符:Test operator+(const Test& rhs) && 中的&&表示这个函数只能被右值对象调用。当str2 + "test"返回临时右值后,后续的+ str2会触发这个版本,直接在临时对象的内存上追加内容,避免新对象的内存分配和拷贝。
  2. 移动语义的利用:右值版operator+最后用std::move(*this)返回,触发移动构造函数,把修改后的临时对象资源直接转移给最终的res,无额外开销。
  3. 复用operator+=:把字符串拼接的核心逻辑放在operator+=中,左值和右值版的operator+都基于它实现,减少代码冗余。

运行输出验证

执行上述代码后,你会看到输出类似:

[触发] 拷贝构造
[触发] 左值版operator+
[触发] 移动构造
[触发] 右值版operator+
[触发] 移动构造
内容:hellotesthello

可以看到,str2 + "test"触发左值版operator+和一次移动构造;后续的+ str2触发右值版operator+和一次移动构造,全程没有多余的拷贝操作,达到了优化效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:45:33