提问者:小点点

如果块调用函数时如何使用复制省略


在下面的代码段中,由于复制选择,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链接


共2个答案

匿名用户

在这种特殊情况下,您可以使用三元条件:

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来处理生存期问题。