Copy Elision是C++编译器直接在目标位置构造对象、跳过拷贝/移动操作的优化机制,C++17起对prvalue初始化等场景强制要求;它不调用拷贝/移动构造函数,故不可依赖其副作用。
Copy Elision(拷贝省略)是C++编译器在特定语义场景下,直接在目标位置构造对象、跳过拷贝或移动构造过程的优化机制。它不是“优化拷贝”,而是彻底不执行拷贝/移动操作——连构造函数和析构函数都不会调用。这种优化从C++98起就存在,C++11标准化,C++17起对部分场景强制要求。
标准明确允许省略拷贝/移动的典型场景有三类:
return MyClass{};。编译器直接在调用者提供的内存中构造该对象,不经过中间临时量。MyClass x; return x;。是否生效依赖实现,但C++17后更稳定;多分支返回(如 if-else 各有一个 return)会显著降低 NRVO 触发概率。MyClass a = MyClass(); 或 MyClass a(MyClass());。C++17起这类写法必须省略拷贝,即使类没有定义拷贝/移动构造函数,代码仍合法。C++17将部分拷贝省略从“可选优化”升级为“强制语义”:
MyClass obj = MyClass{}; 这类初始化中,右侧是 prvalue,编译器不得构造临时对象,必须直接在 obj 的存储位置完成构造。MyClass obj(MyClass{});,且拷贝/移动构造函数被删除或不可访问,编译仍会失败——因为语法上仍要求该函数“存在且可调用”,只是实际不执行。拷贝省略可能让本该执行的构造/析构函数完全“消失”,包括它们的副作用:
立即学习“C++免费学习笔记(深入)”;
std::cout ,开启优化后这行可能永远不打印。
用于调试或教学时,可通过编译器选项观察效果:
-fno-elide-constructors 关闭所有拷贝省略,此时你会看到完整的构造→拷贝→析构链条。