我正在尝试实现两个类,如下面的代码所示,类 A 是更通用的母类,而类 B 是一个专门的子类,它自己声明从第一个类继承的 std::function 。
#include<vector>
#include<iostream>
#include<functional>
struct double_vec
{
std::vector<double> p;
std::vector<double> v;
};
typedef std::function<void ()> i_function;
class A
{
public:
A(){};
A(std::vector<double_vec*> vec, i_function p_function, i_function v_function)
{
this->m_vectors = vec;
this->m_function = p_function;
};
void apply()
{
std::cout << "address after function call: " << &m_vectors << std::endl;
m_function();
};
protected:
i_function m_function;
std::vector<double_vec*> m_vectors;
};
class B: public A
{
public:
B(std::vector<double_vec*> vec)
{
this->m_vectors = vec;
load_functions();
};
private:
void load_functions()
{
m_function = [&]()
{
std::cout << "address after function call: " << &m_vectors << std::endl;
};
};
};
int main()
{
std::vector<std::vector<double_vec>> vectors;
std::vector<B> b;
for(int i=0; i<1; ++i)
{
std::vector<double_vec> temp;
std::vector<double_vec*> reference_vector;
temp.resize(10);
for(int i=0; i<10; ++i)
{
temp.at(i).p.resize(10,1);
temp.at(i).v.resize(10,3);
}
vectors.push_back(temp);
for(int i=0; i<10; ++i)
reference_vector.push_back(&vectors.back().at(i));
B temp_b(reference_vector);
b.push_back(temp_b);
}
b.front().apply();
}
这是我的输出:
address before function call: 0x55a934dc2320
address after function call: 0x7ffc284c1130
当我尝试使用 lambda 从子类中声明的函数访问向量时,我注意到存储的数据不正确,经过进一步分析,类成员的地址在函数调用后发生了变化。 随着 m_vectors 的地址发生变化,它不再指向重要数据,并且访问的数据未定义。
当尝试用最少的代码在代码上重现问题时,我注意到除非我创建了要存储的数据的向量(主函数中的变量向量)和/或所述类的向量(主函数中的 b)函数)问题没有出现。
就像使用单个
std::vector<double_vec>
和 B 类的单个变量时发生的情况一样,我预计类成员 m_vectors
的地址不会改变。
我需要地址不改变才能访问存储的信息
我尝试使用
[this]()
和 [&,this]()
作为 lambda,但都没有改变结果
使用虚方法而不是 std::function 声明函数可以使事情正常工作,但是有一个子类以与 B 类似的方式声明,我需要使用
std::function
来代替,所以这不是一个好的解决方案。
我不确定问题出在哪里,所以如果有人可以向我解释发生了什么,我会很高兴。
这条线有问题:
reference_vector.push_back(&vectors.back().at(i));
它将导致reference_vector
中的
悬空指针。当您不断将更多对象推入
vectors
时,最终 capacity
将填满,并且必须重新分配其内部数组,这会将现有对象重新定位到新的内存地址,从而使您已推入 reference_vector
的指针无效
.
为了避免这种情况,您需要在进入外循环之前使用
vectors.reserve()
。