Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.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++ 右值ref的生存期_C++_C++11_Scope_Rvalue Reference_Rvalue - Fatal编程技术网

C++ 右值ref的生存期

C++ 右值ref的生存期,c++,c++11,scope,rvalue-reference,rvalue,C++,C++11,Scope,Rvalue Reference,Rvalue,下面的代码运行良好,据我所知,每次调用函数时,都会创建一个局部变量(即vector),并且在第一次调用时,所有权将在右值引用中转移,在第二次调用时,所有权将在常量引用中转移(如果我删除了它,它甚至不会编译)。因此,当函数终止时,局部变量实际上并没有消失,而是当main中的引用超出范围时(即在main()的末尾),我认为 #include <iostream> #include <vector> std::vector<int> get_v(void) {

下面的代码运行良好,据我所知,每次调用函数时,都会创建一个局部变量(即vector),并且在第一次调用时,所有权将在右值引用中转移,在第二次调用时,所有权将在常量引用中转移(如果我删除了它,它甚至不会编译)。因此,当函数终止时,局部变量实际上并没有消失,而是当main中的引用超出范围时(即在
main()
的末尾),我认为

#include <iostream>
#include <vector>

std::vector<int> get_v(void)
{
    std::vector<int> v{1,2,3};
    return v;
}

int main() {
    std::vector<int> &&rval_ref = get_v();

    for(unsigned int i = 0; i < rval_ref.size(); ++i)
        std::cout << rval_ref[i] << "\n";

    const std::vector<int> &con_ref = get_v();

    for(unsigned int i = 0; i < con_ref.size(); ++i)
        std::cout << con_ref[i] << "\n";

    return 0;
}
但我认为局部变量在超出范围时会消亡,除非它们前面有一个
static
关键字,或者它们被动态分配,甚至被复制。在这种情况下,不复制向量。也许我的C语言背景使我无法理解这里的概念。你能帮我吗

作为旁注,第一种情况允许您修改向量,而第二种情况显然不允许。我猜第一个是C++11特性,而第二个是传统特性



我刚刚用一个自定义类做了一个示例,复制构造函数将不会被调用,但它将与上面的示例一样工作

您的
get\u v
函数返回一个值,因此
v
超出范围并不重要,因为您返回了它的值

这与:

int a()
{
    int j = 3;
    return j; // returns the *value* of j
}

C++标准允许编译器通过某种方式将代码构造函数逐出代码,将代码> V>代码>调用。C++标准还需要在引用绑定到它时延长临时的生存期。

当编写“代码> STD::vector and rValueRe= GETYVE())时,<这些是
返回v时的概念步骤已到达

  • 将创建一个称为返回值的临时对象。这个对象被初始化,就像是通过
    std::vector x{v}。它“存在”于
    main
    中,当
    main
    中的此语句完成时,它自然会“超出范围”
  • v
    被销毁
  • 参考
    rval\u ref
    绑定到该临时对象。将引用绑定到临时对象会导致对象的生存期延长,以匹配引用的生存期
  • “临时物体”这个名字有点用词不当,因为这个物体实际上可能会持续很长时间,但这是官方名称。“未命名对象”是另一种可能的描述

    您的引用并不是指
    v
    ,而是指它的副本(因为您的函数是按值返回的)。因此,即使
    v
    被销毁,副本也不会被销毁


    由于复制省略,测试代码没有显示复制构造函数调用(上面的步骤1)。复制省略意味着编译器可以选择使用与返回值相同的
    v
    内存空间;并省略
    v
    的析构函数和返回值的复制构造函数(即使这些函数有副作用)。

    get\u v
    通过值而不是引用返回。因此,复制构造函数将被称为@captainobvious?一个朋友告诉我不会的!该副本可能会被省略,但可能不会。这取决于优化。无论哪种方式,您仍在按值返回,因此将创建属于调用方的向量的唯一实例。@CaptainObvlious这对我来说仍然不明显,抱歉!也检查我的编辑。我无法理解这是如何发生的。您返回的副本将成为临时(未命名)对象。你的
    常量&
    然后绑定到未命名的临时文件,给它起一个名字(从而延长它的寿命)。哦,转发它是这里的关键。请你对此进行一点扩展(我非常感谢你给我一些简单的话)或者提供一个解释性的链接?请看维基百科上的和。谢谢大卫。从这里的例子中,我了解到转发与RVO有关(是同一件事吗?我想不是…)。因此,在这种情况下,编译器足够聪明,不会破坏局部变量,而是通过在
    main()
    中为其指定变量名来“重命名”它?我不知道你为什么把我和副本ε联系起来。@gsamaras是对的。看来你明白了。是的,到RVO的链接是错误的。@gsamaras Copy-elision是标准在提到省略的拷贝和移动时使用的,RVO是一种拷贝省略的非正式名称。在抛出和捕获时,以及在复制未绑定的临时对象时(通常发生在RVO之后),也可能发生复制省略。
    int a()
    {
        int j = 3;
        return j; // returns the *value* of j
    }