c++ - 右值引用的生命周期

标签 c++ c++11 scope rvalue-reference rvalue

下面的代码工作正常,据我所知,每次调用该函数时,都会创建一个局部变量(即 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;
}

输出:

gsamaras@pythagoras:~$ g++ -std=c++0x -Wall px.cpp
gsamaras@pythagoras:~$ ./a.out
1
2
3
1
2
3

但我认为局部变量在超出范围时就会消失,除非在它们之前有 static 关键字,或者它们已被动态分配,甚至被复制。在这种情况下, vector 不会被复制。也许我的 C 背景使我无法理解这里的概念。你能帮帮我吗?

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


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

最佳答案

当你写 std::vector<int> &&rval_ref = get_v();这些是 return v; 时的概念性步骤达到了

  1. 创建了一个称为返回值 的临时对象。该对象被初始化为 std::vector<int> x{v}; .它“生活”在 main 中当 main 中的此语句时,自然会“超出范围”已经完成了。
  2. v被摧毁
  3. 引用文献 rval_ref绑定(bind)到该临时对象。将引用绑定(bind)到临时对象会导致对象的生命周期延长以匹配引用的生命周期。

“临时对象”这个名称有点用词不当,因为该对象实际上可能会持续很长时间,但这是正式名称。 “未命名对象”是另一种可能的描述。

您的引用资料未提及 v ,它们引用它的拷贝(因为您的函数按值返回)。所以即使v被销毁,拷贝未被销毁。

由于复制省略,您的测试代码未显示复制构造函数调用(上述第 1 步)。复制省略意味着编译器可能会选择为 v 使用相同的内存空间。因为它会用于返回值;并省略 v 的析构函数以及返回值的复制构造函数(即使这些函数有副作用)。

关于c++ - 右值引用的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32194231/

相关文章:

C++11 - typeid 唯一性

c++ - 无法让我的数组编号与另一组进行比较

c++ - 将模板函数指针作为模板参数传递给模板过于冗长

c++ - 是否可以在按值捕获后检测异常切片?

javascript - Angularjs 监视父作用域的变化

c++ - 告诉 VS2010 折叠区域

c++ - 我的 MakeFile 找不到我的头目录

c++ - 什么是 move 语义?

javascript - 默认情况下实现本地作用域的成本

c++ - 范围与变量的生命周期