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

为什么移动构造函数没有被调用?

为什么移动构造函数没有被调用?

我来帮你拆解这个问题,你之所以看不到移动构造函数被调用,主要有两个核心原因:


1. 你的代码触发的是「参数化构造函数」,而非移动构造的场景

先看这句关键代码:

Mystring larry2 = "some larry";

这里的右操作数是字符串字面量"some larry",它的原生类型是const char[11],会自动退化为const char*。而你的移动构造函数Mystring::Mystring(Mystring &&source)只接受**Mystring类型的右值**,根本不处理const char*类型的输入。

所以编译器的第一步动作是:调用你的参数化构造函数(Mystring(const char*)),把const char*转换成一个临时的Mystring对象。


2. 编译器的「拷贝消除」优化跳过了移动步骤

按照C++的原始规则,在临时对象创建完成后,应该用这个临时对象(它是Mystring的右值)调用移动构造函数来初始化larry2。但几乎所有现代编译器都会触发**拷贝消除(Copy Elision)**优化——简单说就是编译器会直接跳过临时对象的创建,直接用参数化构造函数初始化larry2,完全省去了移动的环节。

这就是你只看到「param ctor called」输出的原因。


怎么验证移动构造确实能被触发?

如果你想看到移动构造函数被调用的场景,可以做这两个尝试:

尝试1:显式生成Mystring右值,关闭编译器优化

比如修改代码为:

Mystring larry2 = Mystring("some larry");

然后在编译时关闭拷贝消除优化(比如GCC/Clang用-fno-elide-constructors参数),这时你会看到输出顺序是:

param ctor called
move ctor called
dtor called: some larry  // 临时对象的析构
...

尝试2:对已有的Mystring对象使用std::move

比如:

Mystring temp("temp string");
Mystring larry3 = std::move(temp); // 这里一定会触发移动构造

std::move的作用是把temp这个左值强制转换成Mystring&&类型的右值,这时编译器就会调用你的移动构造函数来初始化larry3。


额外补充

你可能误以为字符串字面量会直接触发移动构造,但记住:移动构造函数的核心是转移已有Mystring对象的资源,而不是从原始字符串字面量创建新对象。从const char*创建Mystring的工作,本来就该是参数化构造函数的职责哦。

备注:内容来源于stack exchange,提问作者gaurav s

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:18:03