复制省略符并在返回值中移动语义

时间:2018-07-07 16:15:43

标签: c++ c++11

背景。

我曾经写过C ++代码,现在我又重新开始了。我正在阅读一些涵盖c ++ 11(及更高版本)功能的书。堆栈溢出也有许多复杂的答案,但我只需要一个简单的答案。

在处理指针时,我通常遵循着名的三个规则,但是现在我看到了新的 move语义,因此该规则已重命名为五个规则。在线阅读我已经看到C ++进化了,现在也有了复制省略。我现在有很多新概念。看这个:

struct Test {};

auto getNewTest() { return Test(); }
auto x = getNewTest();

在这种情况下(假设启用了复制删除功能),唯一出现的复制应该是当我将值分配给x(仅1个副本)时。相反,以前有2个副本:1个为返回值,1个为赋值x。

到目前为止还不错,但是有了移动语义,我可以达到相同的目的(如果我是对的)!假设Test已正确分配了移动操作;我可以这样称呼:

auto getNewTest() { return Test(); }
auto x = std::move(getNewTest());

问题

我了解到,当我必须摆脱旧变量时,移动是一件好事,而不是将其复制到新变量中,而是可以将其所有内容移动到新变量中。

碰巧我有一个像return SomeClass(1,2,3)这样的语句,并且我想避免太多副本。 std :: move()是否做零份?因为复制省略避免1个复制(返回值),并且由于复制构造函数而仅执行1个复制。

我的猜测是,我使用std :: move()窃取了从函数创建的对象,因此我的副本为零。我对么?通常这可能是平庸的,但对我来说却花费了很多时间。

1 个答案:

答案 0 :(得分:1)

您想得太多。编写代码后,

begin
  for cur_r in (select ename, ssno, empno, sal from emp) loop
    begin
      insert into ok_data (ename, ssno, empno, sal)
        values (cur_r.ename, cur_r.ssno, cur_r.empno, cur_r.sal);

    exception
      when others then
        insert into failed_data (ename, ssno, empno, sal) 
          values (cur_r.ename, cur_r.ssno, cur_r.empno, cur_r.sal);
    end;
  end loop;
end;

实际上是在适当的位置构造auto x = getNewTest(); ,这与您获得的效率差不多。

这种行为在C ++ 17中得到了保证,但实际上,这种行为已经存在了很长时间。

更多here。我不推荐cppreference太高,尽管它不是权威。