Maj*_*aha 3 c++ lambda shared-ptr
我在制作一个包含lambda表达式和共享工作指针的普通C ++项目时遇到了问题。该项目在Visual Studio,Debug,x64中。这是我的代码。
Class1.h:
#pragma once
#include <functional>
class Class1
{
int m_data;
const int* m_data_ptr;
public:
std::function<int(int)> m_func;
Class1(int, int);
void Assign(const int&);
};
Run Code Online (Sandbox Code Playgroud)
Class2.h:
#pragma once
#include "Class1.h"
class Class2
{
Class1 m_class1obj;
public:
Class2(int, int);
void Assign(const int&);
int Compute(int);
};
Run Code Online (Sandbox Code Playgroud)
main.cpp:
#include <iostream>
#include "Class1.h"
#include "Class2.h"
Class1::Class1(int i, int j) : m_data(j), m_data_ptr(nullptr)
{
m_func = [i, this](int x)
{
int val = *m_data_ptr;
return (val + m_data + i)*x;
};
std::cout << "Creating class1 object!\n";
}
void Class1::Assign(const int& v)
{
m_data_ptr = &v;
}
Class2::Class2(int i, int j) : m_class1obj(i, j)
{
std::cout << "Creating class2 object!\n";
}
void Class2::Assign(const int& v)
{
m_class1obj.Assign(v);
}
int Class2::Compute(int v)
{
return m_class1obj.m_func(v);
}
int main()
{
int val = 4;
/*
Class2 class2obj(3, 5);
class2obj.Assign(val);
std::cout << class2obj.Compute(23.0) << std::endl;
*/
std::shared_ptr<Class2> class2_ptr;
class2_ptr = std::make_shared<Class2>(Class2(3, 5));
class2_ptr->Assign(val);
std::cout << class2_ptr->Compute(23) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
代码可以正常编译,但是在执行的最后一行时会崩溃main()。在调试时,我发现问题发现的自身行完成后,class2_ptr = std::make_shared<Class2>(Class2(3, 5));出于某种原因,当拉姆达在线路m_func = ...捕捉this指针指向Class1对象的施工时间,它记录了对智能指针后,变成从对象的地址,右不同的地址Class2已创建!似乎第一个记录的地址已过时。调用时class2_ptr->Compute(23),int val = *m_data_ptr;即使在class2_ptr->Assign(val);调用之前分配了非空地址,我最终还是在处引用了空指针,从而导致崩溃m_func。但是为什么地址this更改?是因为对象的内部重新分配对用户隐藏了吗?如果是这样,编译器为什么不重新分配thisin的存储值m_func?此外,尽管具有该物体的错误的地址Class1条记录中m_func,其他的数据成员m_data与在正确的值访问m_func。
重要的是,如果我注释掉main()的最后四行并删除其他三行的注释,则程序不会崩溃!显然,使用共享指针与它有关。在这种情况下,不正确使用lambda表达式或智能指针是否存在问题?我似乎无法在C ++标准中找到适合我的情况的解释。
感谢您对所有解释一切的评论!
std::make_shared<Class2>(Class2(3, 5))创建一个临时文件Class2,将其移到shared_ptr存储中,然后将其销毁。
您的lambda会捕获该临时地址,并在销毁该临时地址后使用它。
您需要避免创建临时文件并Class2直接在shared_ptr存储空间中构建:std::make_shared<Class2>(3, 5);。
甚至更好,摆脱lambda。我不确定为什么要在那里使用它。
| 归档时间: |
|
| 查看次数: |
63 次 |
| 最近记录: |