Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/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++ C++;ABI处理RVO和NRVO?_C++_Abi_Rvo_Nrvo - Fatal编程技术网

C++ C++;ABI处理RVO和NRVO?

C++ C++;ABI处理RVO和NRVO?,c++,abi,rvo,nrvo,C++,Abi,Rvo,Nrvo,我对编译器和链接器如何处理函数调用er的要求因函数使用RVO或NRVO而不同这一事实感到困惑 这可能是我的误解,但我的假设是,通常没有RVO或NRVO std::string s = get_string(); 如果get_字符串不为N?RVO,则涉及从get_字符串的结果中移动s的构造,但如果get_字符串不为N?RVO,则调用代码不执行任何操作,s由函数get_字符串就地构造 编辑: 下面是我如何想象在没有N?RVO的情况下让字符串调用者运行: 调用get_string() get_字符串

我对编译器和链接器如何处理函数调用er的要求因函数使用RVO或NRVO而不同这一事实感到困惑

这可能是我的误解,但我的假设是,通常没有RVO或NRVO

std::string s = get_string();
如果get_字符串不为N?RVO,则涉及从get_字符串的结果中移动s的构造,但如果get_字符串不为N?RVO,则调用代码不执行任何操作,
s
由函数get_字符串就地构造

编辑: 下面是我如何想象在没有N?RVO的情况下让字符串调用者运行:

  • 调用get_string()
  • get_字符串结果现在位于堆栈上,调用方使用它来构造
  • 现在是RVO

  • 调用get_string()
  • 当get_string完成时,堆栈上没有结果,get_string被构造成s,调用方不需要做任何事情来构造s

  • 无论发生什么情况,调用者都会为返回对象分配空间。从调用方的角度来看,函数是否使用RVO并不重要

    您还混淆了两个单独的副本省略。有一个RVO,它省略了从函数局部变量到返回值的副本,还有一个从函数返回值到被初始化对象的副本,也经常被省略

    基本上,在没有任何省略的情况下,您可以将OP的调用看作是这样的(忽略任何别名问题,这实际上都是直接在汇编中实现的):

    字符串
    ret
    被复制(本例中为移动)两次:一次从
    ret
    复制到
    retval
    缓冲区,一次从
    retval
    复制到
    s

    现在,应用NRVO后,只有
    get\u string
    的定义会更改:

    void get_string(void* retval)
    {
        std::string& ret = *new(retval) std::string;
        // do stuff to ret
    }
    
    从来电者的角度来看,一切都没有改变。函数只是直接初始化要返回的对象,使其进入调用者为返回值分配的空间。现在字符串只移动一次:从
    retval
    s

    现在,调用方还可以删除副本,因为不需要分配单独的返回值,然后将其复制到正在初始化的对象中:

    char retval[sizeof(std::string)];
    get_string(retval);
    std::string& s(*(string*)retval);
    

    通过这种方式,
    s
    get\u string
    直接初始化,并且不执行任何复制或移动。

    可能的复制不完全是,我知道RVO在概念上的作用。我想知道它是如何在ABI中实现的,因为调用者需要知道被调用者是如何实现的(或者我错了吗?)。它是堆栈,所以链接器不在乎。编译器只是在堆栈上一个接一个地排列变量。然后,所有变量访问都是当前堆栈顶部的反向引用。在调用之前创建的变量将稍微向下一点。@Galik-编辑的问题
    char retval[sizeof(std::string)];
    get_string(retval);
    std::string& s(*(string*)retval);