在下面的代码段中,由于复制选择,a
不会发生移动和复制
struct A;
A function1();
A function2();
int main(int argc, char**) {
if (argc > 3) {
A a = function1();
} else {
A a = function2();
}
return 0;
}
这很好,但是a
在if-block之外是不可访问的。 在外部声明a
时,将发生移动
struct A;
A function1();
A function2();
int main(int argc, char**) {
A a;
if (argc > 3) {
a = function1();
} else {
a = function2();
}
return 0;
}
当在调用站点上的if块中复制删除到if范围之外的变量时,从复制删除中获利的推荐方式是什么?
编译器-Exlorer链接
在这种特殊情况下,您可以使用三元条件:
A a = argc>3 ? function1() : function2();
在更复杂的情况下,您可能需要保存条件并进行几项检查,例如。
const bool cond = argc>3;
A a = cond ? function1() : function2();
A b = cond ? function3() : function4();
通常,您必须使用placement new来执行以下操作:
template<class T>
struct box {
char buf[sizeof(T)]; // real code should handle alignment
T *p{}; // will point to buf
void reset() {
if(p) p->~T();
p=nullptr;
}
~box() {reset();}
};
void f() {
box<A> a;
if(…) a.p=new (a.buf) A(function1());
else a.p=new (a.buf) A(function2());
// use *a.p
}
这允许围绕初始化的任意语句,以及重复使用单个变量等。
box
只是std::optional
的一个重新实现,具有允许直接new
的勇气; 当然,将它包装在一个函数中会为从任何函数返回的a
实现一个临时值。 box::p
避免了必须使用std::launder
来处理生存期问题。