右值ref的生命周期
Lifetime of rvalue ref
下面的代码工作得很好,据我所知,每次调用函数时,都会创建一个局部变量(即向量),并且在第一次调用时将所有权转移到右值引用中,并在第二次调用时转移到const引用中(如果我删除它甚至不会编译)。因此,当函数终止时,局部变量实际上并没有死亡,但是当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
关键字,或者它们已经被动态分配,甚至被复制。在这种情况下,不复制向量。也许我的C背景让我无法理解这里的概念。你能帮我一下吗?
作为旁注,第一种情况允许修改向量,而第二种情况显然不能。我猜第一个是c++ 11的特性,而第二个是传统的。
我刚刚用一个自定义类做了一个例子,复制构造函数不会被调用,但它会像上面的例子一样工作!
当你写std::vector<int> &&rval_ref = get_v();
时,这些是达到return v;
时的概念步骤
- 创建一个临时对象,称为返回值。该对象与
std::vector<int> x{v};
一样初始化。它"存在"在main
中,并且当main
中的此语句完成时自然会"超出范围"。 -
v
被销毁 - 引用
rval_ref
被绑定到这个临时对象。将引用绑定到临时对象会导致对象的生存期延长,以匹配引用的生存期。
"临时对象"这个名字有点用词不当,因为对象实际上可能会持续很长时间,但这是正式名称。"未命名对象"是另一种可能的描述。
你的引用不指向v
,它们指向它的副本(因为你的函数按值返回)。因此,即使v
被销毁,副本也不会被销毁。
v
使用与返回值相同的内存空间;并省略v
的析构函数和返回值的复制构造函数(即使这些函数有副作用)。
您的get_v
函数返回一个值,因此v
超出作用域并不重要,因为您返回其值。
和
没有区别int a()
{
int j = 3;
return j; // returns the *value* of j
}
c++标准允许编译器通过某种方式将v
转发给调用者来省略复制构造函数。c++标准还要求,如果将引用绑定到临时对象上,则需要延长其生命周期。
相关文章:
- 如何在共享库的整个生命周期内存储数据
- 如何理解句子的生命周期始于对e的评估
- 它解决了什么问题,对于非真空初始化,生命周期在初始化之前就开始了
- Go/C++gRPC客户端通道和存根生命周期
- 如何将"this"的生命周期移动到C++中的另一个对象中?
- 是否可以通过使用移动/交换 c++11 来延长返回的临时变量的生命周期
- 使用对象的生命周期作为设置器的安全性
- 临时人员的生命周期传递给函数
- 我想知道在构造函数中初始化变量时的生命周期
- Lua 用户数据生命周期管理
- 如何使用 epoll(void* event.data.ptr) 管理 Connection 的生命周期
- C++引用的生命周期
- 在堆栈上有一个对象,而不是在函数的整个生命周期内
- 在 Boost ASIO 服务器中处理生命周期
- C++ lambda 生命周期
- 使用互斥锁跟踪另一个应用的生命周期
- QSharedPointer 或 std::shared_ptr 的生命周期
- 来自async_resolve的 boost::asio::ip::tcp::resolver::iterator 的生命周期是多久?
- 如何调整属于类的唯一指针的字符数组的大小.它必须在程序的整个生命周期中保持活力
- 延长 std::tuple<int&,int> 的生命周期,方法是将其分配给 const std::tuple<int, int>&