struct VV
{
~VV(){a = 10; cout<<"------------------------------"<<endl;}
shared_ptr<void> get(){
void* pNew =malloc(10);
return shared_ptr<void>(pNew, [this](void*p){
cout<<"a:"<<a<<endl;
});
int a=1000;
}
int main(int argc, char**argv)
{
{
share_ptr<void> p = nullptr;
{
VV v;
p = v.get();
}
}
return 0;
}
为啥v的生命周期先结束(先析构了), 为啥p回收时候还能正常使用a,而且同时能正常回收内存?
在 C++ 中,当一个对象的生命周期结束时,它的析构函数将被调用。在这个例子中,VV类的析构函数被调用时,会输出一条消息并将成员变量a设置为10。因此,在VV对象v的生命周期结束时,会输出一条消息并将a设置为10。
接着,这个程序中的get函数返回一个shared_ptr对象,其指向一个新分配的内存块,并且使用一个lambda表达式作为其自定义删除器。这个lambda表达式通过捕获this指针,可以访问VV对象v的成员变量a。
当VV对象v被析构时,会释放get函数中分配的内存。在这个过程中,shared_ptr对象p的引用计数减少,并且当引用计数变为0时,p的析构函数也将被调用,从而调用自定义删除器。
在自定义删除器中,它输出当前VV对象v的成员变量a的值。由于这里捕获的是this指针,所以在自定义删除器被调用时,它访问的是已经析构的VV对象v的成员变量a的值,即为10。同时,这个删除器也会释放先前分配的内存块。
因此,p对象在被析构时,能够正常访问a的值,并且能够正常释放分配的内存块,是因为自定义删除器中捕获的是VV对象v的this指针,而不是shared_ptr对象p的指针。这样,即使VV对象v已经被析构,自定义删除器仍然可以访问它的成员变量a的值。
参考GPT和自己的思路:
首先,这段代码存在语法错误,正确的代码为:
struct VV
{
~VV() { a = 10; cout << "------------------------------" << endl; }
shared_ptr<void> get() {
void* pNew = malloc(10);
return shared_ptr<void>(pNew, [this](void* p) {
cout << "a:" << a << endl;
});
}
int a = 1000;
};
int main(int argc, char** argv)
{
{
shared_ptr<void> p = nullptr;
{
VV v;
p = v.get();
}
}
return 0;
}
接着,对于你的问题,原因如下:
在main函数中,VV v是在局部作用域中定义的对象,当程序执行到离开v所在的作用域时,v会被销毁,析构函数也会被调用。此时,a会被赋值为10,输出"------------------------------"。
在get函数中,返回类型为shared_ptr,所以p的生命周期是由shared_ptr进行管理的。在shared_ptr的构造函数中,传入了pNew和一个lambda表达式,用来在shared_ptr析构时回收内存。lambda表达式中使用了this指针,因此可以访问VV中的成员变量a。但是lambda表达式执行的时机是在shared_ptr析构时,也就是p的生命周期结束时。所以此时能正常使用a,并且回收内存。
总而言之,VV的生命周期结束并不会对p产生任何影响,因为p由shared_ptr进行管理。shared_ptr的析构函数中执行的lambda表达式也不会对VV的成员变量a产生影响,因为lambda表达式执行的时机是在p的生命周期结束时。
因为v是在块里定义的,块结束了v就析构了
而p是在外层的块里定义的,它先定义,后析构
而get函数里使用了动态内存,所以即使p回收了动态内存依旧不回收
至于正常回收内存,是因为整个进程都退出了,当然所有内存都回收了
计算机组成原理→Shell命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……
对学习编程者的忠告:
多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!)
单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。