如何在C++20中强制复制消除?确保无拷贝/移动构造并添加编译检查
解决方案说明
首先明确关键规则:C17强制的是临时对象的返回值优化(RVO),但具名局部变量的返回值优化(NRVO)在C17/C++20中仍属于可选优化——不过我们可以通过代码修改来强制实现你的需求,且让编译器在无法满足时报错。
一、确保无拷贝/移动、无局部对象析构的两种写法
1. 直接返回初始化临时对象(利用C++17强制RVO)
修改函数为直接构造并返回临时对象,这种写法在C++17及以后必须执行复制消除:
Object f() { return Object{.value = 10, .str = "example function"}; }
- 效果:编译器会直接在调用方接收返回值的内存位置构造
Object,不会产生任何临时对象,自然不会调用拷贝/移动构造函数,也不存在局部对象的析构(因为根本没有定义局部变量x)。
2. 保留局部变量写法,强制触发NRVO
如果你一定要保留局部变量x的操作逻辑,可以通过删除Object的拷贝/移动构造函数,迫使编译器必须执行NRVO才能通过编译:
首先修改Object类的定义:
class Object { public: int value; std::string str; // 保留默认构造函数(如果需要) Object() = default; // 删除拷贝构造与移动构造 Object(const Object&) = delete; Object(Object&&) = delete; // 同时删除拷贝赋值与移动赋值(可选,但保持一致性) Object& operator=(const Object&) = delete; Object& operator=(Object&&) = delete; };
然后你的原函数f()可以保持不变:
Object f() { Object x; x.value = 10; x.str = "example function"; return x; }
- 效果:由于拷贝/移动构造被删除,编译器如果无法执行NRVO,就会因无法完成返回操作而报错;而NRVO生效时,局部变量
x会直接在调用方的目标内存中构造,函数返回时不会触发x的析构函数,也不会调用任何拷贝/移动构造。
二、强制编译器在无法满足要求时终止编译
上面的第二种方法就是最直接的手段:通过删除Object的拷贝/移动构造函数,让编译器只有在能执行NRVO的情况下才能通过编译——只要编译器无法完成优化,就会抛出编译错误,完全不给它选择的余地。
对于第一种直接返回临时对象的写法,C标准已经强制要求编译器执行复制消除,所以只要你使用C17及以后的编译标准(如-std=c++17或-std=c++20),编译器就必须遵守,不存在无法满足的情况。
内容的提问来源于stack exchange,提问作者Anne Quinn
相关产品推荐
相关产品推荐

