Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 C++;返回值和移动规则异常 当我们从C++函数返回一个值时,复制初始化发生。例如: std::string hello(){ std::string x=“Hello world”; 返回x;//复制初始化 }_C++11_Initialization_Move_Copy Constructor_Rvo - Fatal编程技术网

C++11 C++;返回值和移动规则异常 当我们从C++函数返回一个值时,复制初始化发生。例如: std::string hello(){ std::string x=“Hello world”; 返回x;//复制初始化 }

C++11 C++;返回值和移动规则异常 当我们从C++函数返回一个值时,复制初始化发生。例如: std::string hello(){ std::string x=“Hello world”; 返回x;//复制初始化 },c++11,initialization,move,copy-constructor,rvo,C++11,Initialization,Move,Copy Constructor,Rvo,假设RVO已禁用 根据copyinit规则,如果x是非POD类类型,则应调用复制构造函数。然而,对于C++11以后的版本,我看到调用了move构造函数。我无法找到或理解关于这方面的规则。所以我的第一个问题是—— 当函数从函数返回时,C++标准对复制事件发生的原因是什么? 作为对上述问题的延伸,我还想知道在哪些情况下不采取行动。我提出了以下情况,即调用复制构造函数而不是移动: std::string hello2(std::string¶m){ 返回参数; } 最后,在一些库代码中,我看

假设RVO已禁用

根据copyinit规则,如果
x
是非POD类类型,则应调用复制构造函数。然而,对于C++11以后的版本,我看到调用了move构造函数。我无法找到或理解关于这方面的规则。所以我的第一个问题是——

当函数从函数返回时,C++标准对复制事件发生的原因是什么?

  • 作为对上述问题的延伸,我还想知道在哪些情况下不采取行动。我提出了以下情况,即调用复制构造函数而不是移动:

  • std::string hello2(std::string¶m){
    返回参数;
    }
    
    最后,在一些库代码中,我看到返回时显式使用了
    std::move
    (即使发生了RVO或move)。例如:

    std::string hello3(){
    std::string x=“Hello world”;
    返回std::move(x);
    }
    
  • 返回时显式使用
    std::move
    的优点和缺点是什么

  • 通过move构造函数初始化是“复制初始化”的一个特例,并且不是单独的概念,这一事实让您感到困惑。检查cppreference页面上的注释

    如果另一个是右值表达式,则将通过重载解析选择移动构造函数,并在复制初始化期间调用该构造函数。没有移动初始化这样的术语

    要从函数返回值,请选中。它在一个名为“从局部变量和参数自动移动”的框中显示,其中表达式指的是您返回的内容(警告:该引号缩短了!有关其他情况的详细信息,请阅读原文):

    如果表达式是一个id表达式(可能用括号括起来),该表达式将类型为[…]的变量命名为非易失性对象类型[…],并且该变量在正文中声明为[…],或作为[…]函数的参数,然后,选择用于初始化返回值的构造函数的重载解析将执行两次:第一次好像表达式是右值表达式(因此它可能会选择移动构造函数),如果第一次重载解析失败[…],则重载解析将照常执行,将表达式视为左值(因此它可以选择复制构造函数)

    因此,在返回局部变量的特殊情况下,可以将该变量视为r值,即使正常的语法规则会使其成为l值。该规则的精神在于,在返回后,您无法发现局部变量的值在返回值的复制初始化期间是否已被破坏,因此移动它不会造成任何损害

    关于你的第二个问题:,因为不管怎样搬家都会发生

    引用上面链接的C++核心指南:

    切勿写入
    返回移动(局部变量),因为语言已经知道该变量是移动候选变量。在这段代码中写入
    move
    不会有帮助,实际上可能是有害的,因为在某些编译器上,它会通过为局部变量创建额外的引用别名来干扰RVO(返回值优化)

    因此,您引用的库代码是次优的


    此外,不能从非本地的任何对象隐式移动到函数(即本地变量和值参数),因为隐式移动可能从函数返回后仍然可见的对象移动。在引用cppreference时,重点是“非易失性对象类型”。当您返回
    std::string¶m
    时,这是一个引用类型的变量。

    查找“NRVO”以了解这种情况这是否回答了您的问题:这里缺少的关键点是C++11中return语句的语义