gpt4 book ai didi

c++ - Lambda 函数捕获错误的 "this"指针

转载 作者:太空狗 更新时间:2023-10-29 20:08:13 26 4
gpt4 key购买 nike

我在制作一个涉及 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&);
};

Class2.h:

#pragma once
#include "Class1.h"

class Class2
{
Class1 m_class1obj;
public:
Class2(int, int);
void Assign(const int&);
int Compute(int);
};

主要.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;
}

代码编译正常,但在执行 main() 的最后一行时崩溃.在调试时,我发现问题在完成 class2_ptr = std::make_shared<Class2>(Class2(3, 5)); 行后自行发现。出于某种原因,当 lambda 符合 m_func = ... 时捕获 this指向 Class1 的指针对象的构造时间,它记录了Class2的智能指针之后与对象地址不同的地址。已经被创造了!似乎第一个记录的地址已经过时了。当我调用 class2_ptr->Compute(23) ,我最终在 int val = *m_data_ptr; 取消引用空指针,从而导致崩溃,即使我在 class2_ptr->Assign(val); 中分配了一个非空地址在打电话之前 m_func !但是为什么this的地址没有改变?这是因为对用户隐藏了内存中对象的内部重新分配?如果是这样,为什么编译器不重新分配 this 的正确值?在 m_func 的存储中?此外,尽管 Class1 的对象地址错误记录在 m_func , 另一个数据成员 m_datam_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。我不确定你为什么要在那里使用它。

关于c++ - Lambda 函数捕获错误的 "this"指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56229067/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com