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

C++20中使用auto初始化对象是否一定会调用移动构造函数?

结论

你的理解不正确,C++20标准下两种写法的执行开销完全一致,不存在任何性能差异。

规则依据

C17引入的强制复制/移动消除规则在C20中完全保留,该规则明确要求:当一个同类型的纯右值被用于初始化对象时,编译器必须直接在目标对象的内存空间上构造对象,跳过中间临时对象的构造、以及后续的复制/移动构造步骤,不需要考虑移动构造函数是否有副作用,该优化是强制要求的,不是可选优化。

你给出的第一种写法:

auto t{ std::thread(hello) };

其中std::thread(hello)是std::thread类型的纯右值,用于初始化同类型的变量t,完全符合强制移动消除的触发条件,编译器会直接在t的内存地址上构造接收hello作为参数的std::thread对象,全程仅调用一次构造函数,不会产生中间临时对象,也不会调用移动构造函数。

两种写法的差异

两种写法仅存在编码风格上的区别,性能、运行逻辑完全一致:

  • 第一种写法遵循「几乎总是auto」的编码规范,变量类型由右侧表达式自动推导
  • 第二种写法显式标注变量类型,代码可读性更偏向类型优先的风格

验证方式

你可以通过自定义包装类的方式验证行为,示例如下:

#include <iostream>

struct Test {
    Test(int) { std::cout << "普通构造\n"; }
    Test(const Test&) = delete;
    Test(Test&&) noexcept { std::cout << "移动构造\n"; }
    ~Test() { std::cout << "析构\n"; }
};

int main() {
    auto t{ Test(1) }; // C++17及以后编译运行,只会输出「普通构造」+「析构」,不会触发移动构造
    return 0;
}

上述代码即使删除了拷贝构造、移动构造带有打印副作用,也可以正常编译运行,且不会触发移动构造调用,足以证明消除是强制生效的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 19:27:03