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

C++构造函数中std::string初始化成员默认是拷贝还是移动?

回答

直接结论

  • 当前你写的m_member{p_member}初始化逻辑,默认执行std::string的拷贝构造,不会自动触发移动语义。
  • 如果你要触发移动语义减少不必要的拷贝开销,必须显式添加std::move(p_member)做类型转换。

原理说明

  1. 你的构造函数采用值传递接收std::string参数:当调用方传入右值(比如示例里用字符串字面量"Test"构造的临时std::string)时,形参p_member本身会通过移动构造生成;如果调用方传入左值,形参p_member本身会通过拷贝构造生成。
  2. 但无论p_member本身是怎么构造出来的,在初始化列表/函数体内,有名字的形参p_member属于左值——C++里所有带名字的变量,不管是局部变量还是函数形参,都是左值。用左值初始化另一个std::string对象时,编译器只会匹配拷贝构造函数,不会自动选择移动构造,毕竟编译器没法擅自判定你后续会不会再用到p_member,不会随便把它的资源转走。
  3. 只有通过std::move(p_member)把它强制转换为将亡值(右值的一种),相当于你手动告诉编译器“这个形参之后不会再用了,可以转走它的资源”,初始化m_member时才会匹配到std::string的移动构造函数,直接把p_member内部持有的堆上字符串资源转移给m_member,省去逐字符拷贝的开销。

推荐写法

修改后的构造函数可以兼顾左右值传参的效率,不需要额外写左值const引用、右值引用两个重载版本,注意std::move定义在<utility>头文件中,需要手动引入:

#include <string>
#include <utility>

class Foo
{
public:
    Foo(std::string p_member) : m_member{std::move(p_member)} {}
private:
    std::string m_member;
};

int main()
{
    Foo f{"Test"};
    return 0;
}

这种写法下,传左值进构造函数时总开销是1次拷贝+1次移动,传右值时总开销是2次移动,比传统的const std::string&传参后拷贝初始化成员的写法(传右值时是1次移动+1次拷贝)在传右值场景下效率更高,代码也更简洁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:09:21